Does a tuple collection construct that queries types and elites translate / copy constructor calls?

Consider the following mypair class (I'm not sure if this is the best way to do something, but it works):

 #include <iostream> struct A { A() {} A(const A&) { std::cout << "Copy" << std::endl; } A(A&&) { std::cout << "Move" << std::endl; } std::string s; }; template <class T0, class T1> struct mypair { T0 x0; T1 x1; }; template <class T0, class T1, int N = -1> struct get_class {}; template<class T0, class T1> struct get_class<T0, T1, 0> { static T0& get_func(mypair<T0, T1>& x) { return x.x0; } static const T0& get_func(const mypair<T0, T1>& x) { return x.x0; } static T0&& get_func(mypair<T0, T1>&& x) { return std::move(x.x0); } }; template<class T0, class T1> struct get_class<T0, T1, 1> { static T1& get_func(mypair<T0, T1>& x) { return x.x1; } static const T1& get_func(const mypair<T0, T1>& x) { return x.x1; } static T1&& get_func(mypair<T0, T1>&& x) { return std::move(x.x1); } }; template <int N, class T0, class T1> auto get(mypair<T0, T1>& x) -> decltype(get_class<T0,T1,N>::get_func(x)) { return get_class<T0,T1,N>::get_func(x); } #define MAKE_PAIR(x1, x2) mypair<decltype(x1), decltype(x2)>{x1, x2} int main() { auto x = MAKE_PAIR(A(), A()); get<0>(x); get<1>(x); } 

(perfect link)

The answer when it is aggregate initialization valid in C ++ 11 says that we can eliminate copies / movements by performing aggregate initialization.

Therefore, we can build mypair with MAKE_PAIR without having to do any movement or copy.

I would like to generalize MAKE_PAIR to MAKE_TUPLE , i.e. accept any number of arguments.

Requirements (as is the case with MAKE_PAIR ):

(1) Types are displayed.
(2) Movements / copies are removed during construction from temporary (i.e. the construction takes place on site).

Existing library solutions (e.g. Boost) would be good, although I would prefer something that accepts rvalue references. Or just the code here is great, or a combination of the two.

If at all possible, I would like it to optimize empty elements, still causing calls to move / copy calls, but I get the feeling that you are asking too much.

+6
source share
2 answers

This function already exists in the C ++ 0x standard library - a std::make_tuple . Even if you are bored, you can make your own.

 template<typename... T> std::tuple<T...> make_tuple(T...&& refs) { return std::tuple<T...> { std::forward<T>(refs)... }; } 
+1
source

make_tuple declared make_tuple(Args&&...) , so make_tuple(A{foo},B{blah}) can and (depending on your compiler calling conventions) almost certainly overcome the moves if you give it temporary arguments in the construct, like indicated above.

You cannot generalize make_tuple to force a construct. Here's a counter example

 struct A { A (int); }; struct B { B (int, int); }; 

If I tried to write my_make_tuple , which would build tuple<A,B> , building in place, it would have to decide that my_make_tuple(1,2,3) equivalent to the value of make_tupe(A{1},B{2,3})

You should immediately notice that my_make_tuple(1,2,3) should be equivalent to the value of make_tupe(B{1,2},A{3})

While constructors A and B can be ambiguously overloaded and given that C ++ is not reflected, it is obvious to me that what you ask for is impossible in the general case.

make_tuple only works because the input types are explicitly separated in the argument list. You do not have to worry about the cost of moving operators, as all reasonable cases are incredibly cheap. In addition, they can be excluded.

If performance is critical, embed the constructors and let the compiler understand this.

+1
source

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


All Articles