std::function::target with template parameter pack gives "error: expected primary-expression"
std::function::target with template parameter pack gives "error: expected primary-expression"
当我尝试使用模板参数包在 std::function
对象上调用方法 target
时,编译器会抛出错误,但如果在代理变量。
示例,修改自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));
}
我尝试了各种其他方式来调用 target
,包括以下方式:
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'
编译器似乎只在使用代理变量时才满足,如下所示:
const std::function<int(int, int)>& func = arg;
auto && ptr = func.target<int(*)(Args...)>(); // OK, but requires specifying the template arguments for func
可以看出,此解决方法与之前的非工作示例不同,仅通过显式指定函数参数而不是依赖参数包。 (我可以用 static_cast 例如 static_cast<std::function<int(int,int)>&>(arg).target<int(*)(Args...)>()
绕过代理变量,但这也需要知道转换的参数。)如果我已经知道将要使用什么参数,那么我就不会使用可变参数模板,因为它不是必需的。但既然我没有,我该如何解决这个问题?我做错了什么,这是一个编译器错误,还是这里到底发生了什么?
注:
作为参考,我正在 Windows 10 上使用 GCC 6.3.0 版和 MinGW 进行编译。
arg.template target<int(*)(Args...)>(
当 std 函数类型依赖于模板参数时,您需要消除歧义。
C++ 在调用函数之前解析模板函数时不知道 arg.target
是模板。它必须在调用之前解析它;这不是宏。
因此,无论何时在依赖于模板参数的上下文中命名类型,或在依赖于模板参数的上下文中实例化模板,都必须告诉解析器。
当我尝试使用模板参数包在 std::function
对象上调用方法 target
时,编译器会抛出错误,但如果在代理变量。
示例,修改自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));
}
我尝试了各种其他方式来调用 target
,包括以下方式:
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'
编译器似乎只在使用代理变量时才满足,如下所示:
const std::function<int(int, int)>& func = arg;
auto && ptr = func.target<int(*)(Args...)>(); // OK, but requires specifying the template arguments for func
可以看出,此解决方法与之前的非工作示例不同,仅通过显式指定函数参数而不是依赖参数包。 (我可以用 static_cast 例如 static_cast<std::function<int(int,int)>&>(arg).target<int(*)(Args...)>()
绕过代理变量,但这也需要知道转换的参数。)如果我已经知道将要使用什么参数,那么我就不会使用可变参数模板,因为它不是必需的。但既然我没有,我该如何解决这个问题?我做错了什么,这是一个编译器错误,还是这里到底发生了什么?
注:
作为参考,我正在 Windows 10 上使用 GCC 6.3.0 版和 MinGW 进行编译。
arg.template target<int(*)(Args...)>(
当 std 函数类型依赖于模板参数时,您需要消除歧义。
C++ 在调用函数之前解析模板函数时不知道 arg.target
是模板。它必须在调用之前解析它;这不是宏。
因此,无论何时在依赖于模板参数的上下文中命名类型,或在依赖于模板参数的上下文中实例化模板,都必须告诉解析器。