When I attempt to call the method target
on a std::function
object using a template parameter pack, the compiler throws an error, but it works fine if the template parameters are specified explicitly in a proxy variable.
Example, modified from cppreference.com:
#include <functional>
#include <iostream>
int f(int, int) { return 1; }
int g(int, int) { return 2; }
template <typename... Args>
void test(std::function<int(Args...)> const& arg)
{
auto && ptr = arg.target<int(*)(Args...)>(); // error: expected primary-expression before 'int'
if (ptr && *ptr == f)
std::cout << "it is the function f\n";
if (ptr && *ptr == g)
std::cout << "it is the function g\n";
}
int test()
{
test<int, int>(std::function<int(int, int)>(f));
test<int, int>(std::function<int(int, int)>(g));
}
I've tried various other ways to call target
including the following:
int (*const* ptr)(Args...) = arg.target<int(*)(Args...)>(); // error: expected primary-expression before 'int'
int (*const* ptr)(int, int) = arg.target<int(*)(Args...)>(); // error: expected primary-expression before 'int'
int (*const* ptr)(int, int) = arg.target<int(*)(int, int)>(); // error: expected primary-expression before 'int'
const std::function<int(Args...)>& func = arg;
auto && ptr = arg.target<int(*)(Args...)>(); // error: expected primary-expression before 'int'
The compiler only appeared to be satisfied when using a proxy variable as seen here:
const std::function<int(int, int)>& func = arg;
auto && ptr = func.target<int(*)(Args...)>(); // OK, but requires specifying the template arguments for func
As can be seen, this workaround deviates from the previous non-working example only by explicitly specifying the function parameters instead of relying on the parameter pack. (I could bypass the proxy variable with a static_cast e.g. static_cast<std::function<int(int,int)>&>(arg).target<int(*)(Args...)>()
, but this also requires knowing the parameters for the cast.) If I already knew what parameters were going to be used then I wouldn't be using a variadic template since it wouldn't be necessary. But since I don't, how can I fix this? Am I doing something wrong, is this a compiler bug, or what exactly is going on here?
Note:
For reference, I'm compiling with GCC version 6.3.0 with MinGW on Windows 10.