I had a problem similar to this one: std::function and std::bind: how to load a std::bind with a function template
I didn't find any satisfactory answer, but my doubt is similar (not the same) as this post above
The code:
#include <iostream>
#include <functional>
using namespace std;
namespace my {
template <typename T>
struct test;
template <typename R, typename ...Ts>
struct test<R(Ts...)>{
test(R(*func)(Ts...)){
//None content, only test
}
};
}
void install1(my::test<int(int, int)> func)
{
}
template <typename R, typename ...Ts>
void install2(my::test<R(Ts...)> func)
{
}
int add(int a, int b)
{
return a + b;
}
int main(int argc, char *argv[])
{
install1(add);
my::test<int(int, int)> fun = add;
install1(fun);
install2<int, int, int>(add);
return 0;
}
void install2
this code
template <typename R, typename A, typename B>
void install2(my::test<R(A, B)> func)
{}
install2<int, int, int>(add);
This code above works fine, but if i remove "A, B" and put "...Ts" the program doesn't compile
Thank in advance, and I apologize for any misunderstanding in the description of the problem (I'm using google translate)
With
template <typename R, typename ...Ts>
void install2(my::test<R(Ts...)> func)
and calling
install2<int, int, int>(add);
you have provided explicit template arguments for the first template parameter and two elements of the parameter pack. But there could still be more elements in the pack. Therefore the function parameter still has a type containing template parameters that need to be deduced (basically my::test<int(int, int, Ts...)>
).
So template argument deduction will be applied to the argument/parameter pair and it will fail, because the function argument you are providing does not have a my::test
type.
With
template <typename R, typename A, typename B>
void install2(const char name[], my::test<R(A, B)> func)
you have provided template arguments to all template parameters explicitly, so my::test<R(A, B)> func
will not be a deduced context anymore.
As mentioned in the comments to the question install2<int, int, int>({add});
also works because the braces make the function argument/parameter pair a non-deduced context.
If you want to be able to call the function with explicit template arguments and without braces, you can make the function parameter always a non-deduced context, for example using C++20's std::type_identity
:
template <typename R, typename ...Ts>
void install2(std::type_identity_t<my::test<R(Ts...)>> func)
However, then it is not possible anymore to call it without an explicit template argument list.
You could use both this version and the original as overloads, forwarding one to the other, to cover all situations you mention in your example code.