Reputation: 81
I am trying to use the std::function::target() in a template. First I tried the example found here: http://www.cplusplus.com/reference/functional/function/target/ It worked well, so I modified it to allow a function to be passed as parameter. This also worked - see test1() in the code listing below.
Then I tried making it more generic, by using a template. See test2() below. But I clearly have not gotten the template correct, and I get the following compiler output:
targetTest.cpp: In function ‘void test2(std::function<int(Args ...)>)’:
targetTest.cpp:36:29: error: expected primary-expression before ‘int’
std::cout << (*foo.target<int(*)(Args...)>())(100,20) << '\n';
^~~
targetTest.cpp:36:29: error: expected ‘)’ before ‘int’
targetTest.cpp:40:15: error: expected primary-expression before ‘int’
*foo.target<int(*)(Args...)>() = &my_minus;
^~~
targetTest.cpp:40:15: error: expected ‘;’ before ‘int’
targetTest.cpp: In function ‘void myTestFunction()’:
targetTest.cpp:47:26: error: no matching function for call to ‘test2<int, int>(int (&)(int, int))’
test2<int, int>(my_plus);
^
targetTest.cpp:27:6: note: candidate: template<class ... Args> void test2(std::function<int(Args ...)>)
void test2(std::function<int(Args...)> foo)
^~~~~
targetTest.cpp:27:6: note: template argument deduction/substitution failed:
targetTest.cpp:47:26: note: mismatched types ‘std::function<int(Args ...)>’ and ‘int (*)(int, int)’
test2<int, int>(my_plus);
Here is my testcode:
// function::target example
#include <iostream> // std::cout, std::boolalpha
#include <functional> // std::function, std::plus, std::minus
int my_plus (int a, int b) {return a+b;}
int my_minus (int a, int b) {return a-b;}
void test1(std::function<int(int,int)> param)
{
std::function<int(int,int)> foo = param;
std::function<int(int,int)> bar = std::plus<int>();
// calling using functional form:
std::cout << foo(100,20) << '\n';
std::cout << bar(100,20) << '\n';
// calling by invoking target:
std::cout << (*foo.target<int(*)(int,int)>())(100,20) << '\n';
std::cout << (*bar.target<std::plus<int>>())(100,20) << '\n';
// changing target directly:
*foo.target<int(*)(int,int)>() = &my_minus;
std::cout << foo(100,20) << '\n';
}
template<typename... Args>
void test2(std::function<int(Args...)> foo)
{
std::function<int(int,int)> bar = std::plus<int>();
// calling using functional form:
std::cout << foo(100,20) << '\n';
std::cout << bar(100,20) << '\n';
// calling by invoking target:
std::cout << (*foo.target<int(*)(Args...)>())(100,20) << '\n';
std::cout << (*bar.target<std::plus<int>>())(100,20) << '\n';
// changing target directly:
*foo.target<int(*)(Args...)>() = &my_minus;
std::cout << foo(100,20) << '\n';
}
void myTestFunction()
{
test1(my_plus);
test2<int, int>(my_plus);
}
Upvotes: 1
Views: 55
Reputation: 62553
The reason for immediate compilation error you are seeing is an annoying requirement to use template
keyword you need to use whenever you are trying to use something as a template, but compiler doesn't know if it is indeed a template. And the reason why compiler doesn't know that target
is a template is because of two-step template instantiation (this topic is greatly researched here on SO and everywhere, so I will not discuss it here).
Here is a fixed line from your sample:
std::cout << (*foo.template target<int(*)(Args...)>())(100,20) << '\n';
This works in this particular place.
However, your code still would not compile, due to the way you are trying to call the templated test2
. Correct way would be:
test2(std::function<int (int, int)>(my_plus));
Which allows compiler to deduce template arguments.
Upvotes: 3