The following (simplified) code does not compile because the compiler cannot deduce a template parameter.
#include <iostream>
#include <utility>
#include <vector>
enum class animal : size_t { cat, dog };
template <animal a, class... U>
using animal_select_t = typename std::tuple_element<static_cast<size_t>(a), std::tuple<U...>>::type;
template <animal a>
using mytype = animal_select_t<a, int, double>;
template <animal a>
void print(std::vector<mytype<a>>&& vec)
{
for (const auto& x : vec)
std::cout << x << std::endl;
vec.resize(0);
}
int main()
{
std::vector<int> v(3, 1);
print(std::move(v));
std::cout << v.size() << std::endl;
return 0;
}
The error message is
deduce.cpp: In function ‘int main()’:
deduce.cpp:24:8: error: no matching function for call to ‘print(std::remove_reference<std::vector<int>&>::type)’
24 | print(std::move(v));
| ~~~~~^~~~~~~~~~~~~~
deduce.cpp:14:6: note: candidate: ‘template<animal a> void print(std::vector<typename std::tuple_element<static_cast<long unsigned int>(a), std::tuple<int, double> >::type>&&)’
14 | void print(std::vector<mytype<a>>&& vec)
| ^~~~~
deduce.cpp:14:6: note: template argument deduction/substitution failed:
deduce.cpp:24:8: note: couldn’t deduce template parameter ‘a’
24 | print(std::move(v));
Apparently, this is a case of a nondeduced context.
Obviously, reducing the "nesting" of template parameters solves the issue. For example, the print
routine can be modified as
template <typename U>
void print(std::vector<U>&& vec)
{
// which animal?
for (const auto& x : vec)
std::cout << x << std::endl;
vec.resize(0);
}
However, this solution is not optimal because
print
can be potentially instantiated with astd::vector
of a type which is not one of the choice given inmytype
In an actual code, I may need to know the actual template parameter
animal a
.
Assuming we use print
as in the second block of code, how can one:
restrict the instantiation to the allowed types,
mytype<a>
, witha
ananimal
?deduce the template parameter
animal
?
Or is there a better solution, implementing differently print
?
Please notice that I am looking for a scalable solution.
Obviously for the example above, the solution is easy, given that only int
and double
are considered.
I am instead looking for a solution that I can generically use even when the enum class animal
and/or the type alias mytype
is changed.
Also, I am looking for a solution in the c++17 standard.