How would you apply the same operation to a set of independent variables in C ++?

Edit I completely forgot to mention something obvious to me:

a_func() wants to change var_xxx , so solutions that iterate using the type const do not completely satisfy (although they give ideas, of course).

I feel the answer is simple, but he cannot find it.

Given:

The number (a small number, for example 6, 8, 10) of variables of the user class type (exactly, a mathematical vector object), where each variable must have a unique name determined by the algorithm (in order to be calculated and then used independently, and to be able to easily consult the paper on which the code is based)

make:

In a piece of code, compute and initialize these variables, referencing them by name; and then, in another piece of code, they perform an operation on them in a scan without the need to duplicate the code that causes the operation (i.e., function) for each variable.

The code is as follows:

 // in a class declaration vector_type var_abc, var_efg, var_xyz; // in a class member function // "some_math_xxx" pieces are coded inline, not as separate functions var_abc = /* some_math_abc */; var_efg = /* some_math_efg */ ; var_xyz = /* some_math_xyz */ ; a_func(var_abc); a_func(var_efg); a_func(var_xyz); 

I mean, I can of course dial a_func(var_xxx) six or more times. But that, well, is simply wrong for me.

Thought of:

  • a hash to store the names of these cars (bad for math, using them later, I think)
  • a std::array<> pointers to var (bit awkward but working)
  • this code that is not compiled:

    for (vector_type& vr : { var_abc, var_efg, var_xyz }) { a_func(vr); } for (vector_type& vr : { var_abc, var_efg, var_xyz }) { a_func(vr); } (error: binding const vector_type to reference of type vector_type& )

How would you solve this? Of course, I would prefer an elegant solution. The standard is best just C ++ 11, although C ++ 14 is also good if it allows you to get a super-nice solution to this problem.

PS The question entry form says: "the name is subjective and Q may be closed." I am sure that this is not based on the opinions of Q, as I am not asking to compare solutions, but to offer some.

+5
source share
5 answers

The problem is that you tried to initialize a link with a const value copied to the implicit initializer_list . This container, like all others, cannot contain links. So, you get const values, since initializer_list (currently? And probably always) offers const access to its members.

So ... just use pointers to elements. They should not be feared. It seems simple:

 for ( auto const it: /* std::initializer_list<VecType *> */ {&vecA, &vecB, &vecC} ) { doStuff(*it); // NB it is a *const, not a const *const! } 

You do not need to explicitly specify the initializer_list type if you do not use elements of different types of polymorphic pointers or which require operator conversion (in this case, you do this).

If I'm missing something, others' suggestions about putting everything through an extra layer of std::reference_wrapper seem to be an unnecessary hoop to slip through, just to avoid pointers for some reason. Other solutions may refer to copies, which can lead to a lot of confusion.

I would like C ++ to have an "automatic gaming" type of range <<299> for this case, but getting this implemented is likely to cause all kinds of syntactic ambiguity, which would not really be worth it.

+4
source

I would write a recursive function that applies a functor to a set of variables:

 #include <functional> template<typename Functor, typename First, typename Second, typename ... Others> auto apply_over(Functor &&fn, First &&var0, Second &&var1, Others &&... vars){ fn(std::forward<First>(var0)); apply_over(std::forward<Second>(var1), std::forward<Others>(vars)...); } template<typename Functor, typename Var> auto apply_over(Functor &&fn, Var &&var){ fn(std::forward<Var>(var)); } 

And use it like this:

 auto main() -> int{ var_type var0, var1, var2; apply_over([](var_type &var){ /* do something with var */ }, var0, var1, var2); } 

Or even better (more general) with C ++ 14:

 auto main() -> int{ var_type var0; int var1; float var2; // no need to worry about types! apply_over([](auto &var){ var += decltype(var)(1); }, var0, var1, var2); } 

Or using your a_func function:

 auto main() -> int{ var_type var0, var1, var2; apply_over(a_func, var0, var1, var2); } 
+4
source

Your code: for (vector_type& vr : { var_abc, var_efg, var_xyz }) { a_func(vr); } for (vector_type& vr : { var_abc, var_efg, var_xyz }) { a_func(vr); } creates initializer_list :

An object of type std::initializer_list<T> is a lightweight proxy object that provides access to an array of objects of type const T

Thus, you cannot call a modifying function on them.

Instead, use ref : for (auto& vr : { ref(var_abc), ref(var_efg), ref(var_xyz) }) { a_func(vr); } for (auto& vr : { ref(var_abc), ref(var_efg), ref(var_xyz) }) { a_func(vr); }

Live example

+3
source

If you want to achieve a copy effect that inserts a function call without actually copying, use this template template trick :

 template<typename ... Args> void call_a_func (Args&&... args) { int unused[] = { (a_func(std::forward<Args>(args)), 0) ... }; (void) unused; } 

Using:

 call_a_func(var_abc, var_efg, var_xyz, var_pqr); 

I simplified your problem in this Demo . You can extend it further. This trick is mentioned in various places in SO, I took from this post .

+2
source

If you need an expanded loop, you might be interested in for_each_arg :

 template<class F, class...Ts> F for_each_arg(F f, Ts&&...a) { return (void)std::initializer_list<int>{(f((Ts&&)a),0)...}, f; } 

Using:

 for_each_arg(a_func, var_abc, var_efg, var_xyz); 

Of course, if you need to work with the same set of variables many times, it is better to define an array of pointers and use iteration.

Literature:

https://twitter.com/ericniebler/status/559119062895431680

https://youtu.be/Za92Tz_g0zQ

https://github.com/SuperV1234/cppnow2015

+1
source

Source: https://habr.com/ru/post/1247037/


All Articles