Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Tuple aggregate construction which infers types and elides move/copy constructor calls?

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

#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);
}

(ideone link)

The answer when is aggregate initialization valid in C++11 says we can elide copies/moves by doing aggregate initialization.

Hence, we can construct mypairs using MAKE_PAIR without the need to perform any moves or copies.

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

Requirements are (as with MAKE_PAIR):

(1) Types are inferred.
(2) Moves/copies are elided when constructing from temporaries (i.e. construction happens in place).

Existing library solutions (e.g. Boost) will be fine, though I'd prefer something which accepts rvalue references. Or just code here is great also, or a mix of the two.

If it is at all possible, I'd like it if it optimized out empty members whilst still eliding moves/copy constructor calls, but I have a feeling that is asking too much.

like image 868
Clinton Avatar asked Jun 08 '11 04:06

Clinton


1 Answers

There is already such a feature in the C++0x Standard Library- a std::make_tuple. Even if you get bored, you can make your own.

template<typename... T> std::tuple<T...> make_tuple(T...&& refs) {
    return std::tuple<T...> { std::forward<T>(refs)... };
}
like image 108
Puppy Avatar answered Oct 26 '22 06:10

Puppy