I am starting to work with templates and I am trying to figure out why the following does not work.
class testclass1
{
public:
template <typename...Ts>
using TFunc = std::function<void(Ts*...)>;
template <typename...Ts>
void SetFunction(TFunc<Ts...> tf)
{
// Do something
}
};
template<typename...Ts>
class testclass2
{
public:
using TFunc = std::function<void(Ts*...)>;
void SetFunction(TFunc tf)
{
// Do something
}
};
void some_function(std::string*, double*)
{
}
int main()
{
testclass1 tc1;
testclass2<std::string, double> tc2;
testclass1::TFunc<std::string, double> tf1 = some_function;
tc1.SetFunction<std::string, double>(tf1);
tc1.SetFunction<std::string, double>(testclass1::TFunc<std::string, double>{tf1});
tc2.SetFunction(some_function);
tc1.SetFunction<std::string, double>(some_function);
}
All works fine except the last version
tc1.SetFunction<std::string, double>(some_function);
which is actually what I would like to do since it has much less boilerplate and since I don't want testclass1 to require template arguments.
The last line gives the following compilation error:
No matching member function for call to 'SetFunction'
- Candidate template ignored: could not match 'function<void (std::__1::basic_string *, double *, type-parameter-0-0 ...)>' against 'void ()(std::__1::basic_string *, double *)'
I don't understand what is the additional "type-parameter-0-0". Intuitively, this looks much like problems linked to an implicit *this pointer, but I don't see why TFunc would be a member function and have an implicit *this pointer (or is this linked to std::function?). Also, moving the code template <typename...Ts> using TFunc = std::function<void(Ts*...)>; outside of testclass1 does not change anything.
From browsing different related Q&As, it seems that you cannot use std::function with template functions. Is this the problem here?
Is there a way to make tc1.SetFunction<std::string, double>(some_function);work within testclass1?
Thanks in advance.
UPDATE: I'm trying to wrap my head around the explanation, I think I sort of get it but then---thinking about it---I'm still not 100% sure. Consider the following code:
template <typename...Ts>
using test_tuple = std::tuple<Ts...>;
template <typename...Ts>
void test_func(test_tuple<Ts...> tup)
{
// Do something
// e.g., PrintTuple(tup);
}
int main()
{
test_tuple<std::string, double> tt{"Hi", 3.1459f};
test_func<std::string>(tt);
}
In that case, only std::string is specified in the parameter pack and the double is deduced (so not all parameters are specified in the pack). But why does it work in this case and I don't get an error?