2

I have the following API to be implemented:

tuple<vector<string>, ItemStatus> SomeFcn() const
{
    vector<string> result_item;
    return tuple(result_item, ItemStatus::ACTUAL );
}

But it does not compile and compile output is not clear at all

/usr/include/c++/9/bits/stl_pair.h:436:9: note: candidate: ‘template<class ... _Args1, long unsigned int ..._Indexes1, class ... _Args2, long unsigned int ..._Indexes2> std::pair<_T1, _T2>::pair(std::tuple<_Args1 ...>&, std::tuple<_Args2 ...>&, std::_Index_tuple<_Indexes1 ...>, std::_Index_tuple<_Indexes2 ...>)’
  436 |         pair(tuple<_Args1...>&, tuple<_Args2...>&,
      |         ^~~~
/usr/include/c++/9/bits/stl_pair.h:436:9: note:   template argument deduction/substitution failed:

Something is wrong at tuple instance creation. I have this code compiled with -std=c++17. ItemStatus is an enum class.

What's wrong here?

Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
Dmitry
  • 1,912
  • 2
  • 18
  • 29
  • 1
    Your question is tagged with C++11 (which does not have class template argument deduction) whereas you mention you are compiling with C++17: what language level are you using? – dfrib Oct 26 '20 at 15:37
  • I compile it with g++ -std=c++17 -O0 -g3 – Dmitry Oct 26 '20 at 15:38
  • I have no compiler at hand currently, so I cannot test this: try wrapping ˋresult_itemˋ with parentheses in the return call. – Mike Lischke Oct 26 '20 at 15:43
  • Did you simply try `return {result_item, ItemStatus::ACTUAL };` ? – Damien Oct 26 '20 at 15:44
  • Have you tried [`std::make_tuple()`](https://en.cppreference.com/w/cpp/utility/tuple/make_tuple) yet? – Remy Lebeau Oct 26 '20 at 15:47
  • Cannot reproduce, see: https://wandbox.org/permlink/QSlMKwScu5dLaEdn. Maybe you just need to remove that `const`, if it's a non-member function. – Paul Sanders Oct 26 '20 at 15:51

2 Answers2

4

Basically, you have three options:

return {result_item, ItemStatus::ACTUAL };
  • Create a tuple object (make_tuple) (AndersK's answer):
return std::make_tuple(result_item, ItemStatus::ACTUAL );
return std::tuple<std::vector<std::string>, ItemStatus>{result_item, ItemStatus::ACTUAL };
Jose
  • 3,306
  • 1
  • 17
  • 22
  • Would using `std::move` improve (or harm) the performance of any of these (assuming `result_item` is in fact a huge `vector`, since a function that always returns an empty one seems kind of pointless)? – ShadowRanger Oct 26 '20 at 16:10
  • 2
    @ShadowRanger: It's already a return statement. The compiler knows that local variables go out of scope and can safely be moved from. – MSalters Oct 26 '20 at 16:11
  • As @MSalters said, I wouldn't do that. In addition, highly related with copy elision and NRVO : https://stackoverflow.com/questions/12953127/what-are-copy-elision-and-return-value-optimization – Jose Oct 26 '20 at 16:18
  • Just to be explicit: you don't want to call `std::move` on the return expression. Calling `std::move` on the arguments to `std::make_tuple` on the other hand would make sense. – MSalters Oct 26 '20 at 16:25
  • @ShadowRanger: Thinking about it more, and seeing that there was no anwer on that yet, I've created a new question: https://stackoverflow.com/questions/64541229/stdmove-in-sub-expressions-of-return-statement – MSalters Oct 26 '20 at 16:34
  • @MSalters: Yeah, that's what I meant. `std::move` of the result of `std::make_tuple` is clearly pointless (copy-elision/RVO handles that), but whether it helps avoid deep-copies of the `vector` wasn't clear; can the compiler adequately optimize the call `std::make_tuple` with the knowledge that `result_item` is expiring, or is that knowledge not available or too complex for most compilers to handle, so `std::move` would be indicated? – ShadowRanger Oct 26 '20 at 16:45
  • @Jose: Looks like you should use `move` though; obviously you shouldn't `move` the `tuple` itself (copy-elision handles that), but the items being added to the `tuple` [should be `move`d to avoid being copied](https://stackoverflow.com/q/51521031/364696). – ShadowRanger Oct 26 '20 at 18:57
2

Write like this instead, assuming ItemStatus is an enum

std::tuple<std::vector<std::string>, ItemStatus> SomeFcn() const
{
  std::vector<std::string> result_item;
  return std::make_tuple(result_item, ItemStatus::ACTUAL );
}

(* i don't like leaving namespace out *)

AndersK
  • 35,813
  • 6
  • 60
  • 86