Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++ - std::decay<T> and std::make_tuple<D> - cannot convert argument from 'D' to 'D &&'

I have this code:

template <typename T>
void someFunction(){
   typedef std::decay<T>::type D;

   D val = GetValue<D>();
   std::tuple<D> t = std::make_tuple<D>(val);

   //... tuple is stored outside this scope in global variable
}

GetValue<D>() returns value from dictionary based on typeid(D), it is working correctly and I return MyData to D - I tested it if I comment out the next problematic line, see the problem below.

If I compile this, for T = const MyData & I got this

 error C2664: 'std::tuple<MyData > std::make_tuple<D>(D &&)': cannot convert argument 1 from 'D' to 'D &&'

Why is this error produced and how to remove it? I want to store only non-ref values in my tuple, even if template T is refd'.

I can get it compile, by using std::make_tuple<D>(std::forward<D>(val)), but it calls my move ctor and I want to cal copy ctor, because val is destroyed at the end of method and so its internal data and move ctor just moved them, so they are gone.

like image 959
Martin Perry Avatar asked Sep 12 '25 17:09

Martin Perry


1 Answers

You should never pass explicit template parameters to make_tuple and make_pair. Their power lies exactly in their ability to deduce types, as well as decaying them and unwrapping reference wrappers.

The following should work:

std::tuple<D> t = std::make_tuple(std::move(val)); // forward is superfluous here

or, better yet:

auto t = std::make_tuple(GetValue<D>());
like image 109
krzaq Avatar answered Sep 14 '25 07:09

krzaq