Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/three.js/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++11 C+的奇怪替换失败+;11可变模板_C++11_Variadic Templates - Fatal编程技术网

C++11 C+的奇怪替换失败+;11可变模板

C++11 C+的奇怪替换失败+;11可变模板,c++11,variadic-templates,C++11,Variadic Templates,在这个示例代码中,我很难找出导致替换失败的原因: bool f(int a, int b, float c) { printf("%d %d %f", a, b, c); return true; } template <typename ...Params> void call1(Params... params, std::function<bool(Params...)> func) { func(params...); } templa

在这个示例代码中,我很难找出导致替换失败的原因:

bool f(int a, int b, float c)
{
    printf("%d %d %f", a, b, c);
    return true;
}

template <typename ...Params>
void call1(Params... params, std::function<bool(Params...)> func)
{
    func(params...);
}

template <typename ...Params>
void call2(std::function<bool(Params...)> func)
{
}
bool f(整数a、整数b、浮点c)
{
printf(“%d%d%f”,a、b、c);
返回true;
}
模板
void call1(Params…Params,std::function func)
{
函数(参数…);
}
模板
void call2(std::function func)
{
}
总的来说:

call1<int, int, float>(3, 4, 5.5, f); // Ok.
call2<int, int, float>(f); // Substitution failure.
call1(3,4,5.5,f);//好啊
电话2(f);//替代失败。
编者说:

template argument deduction/substitution failed: mismatched types 'std::function<bool(Params ...)>' and 'bool (*)(int, int, float)'
call2<int, int, float>(f);
                          ^
模板参数推断/替换失败:类型“std::function”和“bool(*)(int,int,float)”不匹配
第2(f)段;
^
让我困惑的是,call1工作,而call2不工作。
有什么建议吗?=)

表达式
f
的类型是指向函数的指针,即
bool(*)(int,int,float)
。然而,
call2
模板的显式实例化具有类型
void foo(std::function)
,即参数类型不同,因此不匹配

解决方法:

auto x = call2<int, int, float>;
x(f);
auto x=call2;
x(f);

利用从函数指针构造
std::function
的可能性。

首先:您可以指定比您使用的更少的参数,并让编译器推断其余参数:

template <typename ...Params>
void func1(Params... params);

func1<int, int>(1, 2, 3); // calls func1<int, int, int>
直接调用
call1
函数时:

template <typename... Params>
void call1(Params... params, std::function<bool(Params...)> func);

call1<int, int, int>(1, 2, 3, f);
call1<int>(1, 2, 3, f); // same as before
call1(1, 2, 3, f); // same as before
在这里,您通知编译器,
Params
的前3个元素都是int
Params={int,int,int,…}
。请注意,它仍然可以添加其他内容(如果扣减说明如此)。我们有:
std::function func
。除非显式传递
std:function
(精确匹配),否则编译器不可能知道此不完整类型的含义。它还不知道它可以有一个构造函数使用您提供的函数指针,因此存在不匹配。现在,编译器没有足够的数据来决定是否需要更多类型进入
Params
。失败

但请注意这个有趣的例子:

auto x = call2<int, int, int>;
x(f); // x is exactly void(*)(std::function<bool(int, int, int)>). No doubts.

编译器无法使用当前代码推断类型(即使函数指针隐式转换为
std::function
)。您可以创建一个traits类来帮助推断正确的类型

template <typename... Params>
struct func_traits {
    using func_type = std::function<bool(Params...)>;
};

template <typename ...Params>
void call2(typename func_traits<Params...>::func_type func) {}
模板
结构函数特性{
使用func_type=std::function;
};
模板
void call2(typename func_traits::func_type func){}

我不知道这是否有帮助,但clang++给出了以下消息:
注意:候选模板被忽略:无法将“function”与“bool(*)(int,int,float)”匹配
。在这里,您可以看到一个额外的
type-parameter-0-0…
参数可能是罪魁祸首。我不知道如何摆脱它。我不明白这其中的逻辑,你是否试图在给模板提供3种类型的同时不带参数地调用f?我仍然不明白你想做什么,但我认为call2中的
f
被解释为int(函数f的地址是该
int
的值)因此,将模板的第二个
int
float
func
参数保留为“undefined”,在这种情况下不可能匹配。我根本不尝试调用f。这是一个演示问题的最小示例。其动机是制作一个函数,自动将字符串列表转换为正确的参数,并将其传递给func。我通过传递一个可调用的模板参数而不是std::函数解决了最初的问题,但我仍然想解决这个谜团。至于你的理论,编译器错误意味着相反。-1因为没有在帖子中包含编译器和版本,因为这会产生巨大的差异。某些常见的编译器(VC11及以下版本)并不真正支持变量并在某些情况下模拟它们。它可能不是解决方案的关键,但它为人们提供了一个开始的地方,并让我们知道您尝试了什么。参数
std::function
具有推断类型,因此它“包含参与模板参数推断的模板参数”当将函数参数与函数参数(14.8.1#6)匹配时,不会执行隐式转换。关于“不可能知道此不完整类型的含义”这就是演绎的目的,调用
call2(std::function(f))没有问题
参数类型是从参数类型推导出来的,不需要像传递普通函数指针那样执行隐式转换。
auto x = call2<int, int, int>;
x(f); // x is exactly void(*)(std::function<bool(int, int, int)>). No doubts.
(&call2<int, int, int>)(f);
template <typename... Params>
struct func_traits {
    using func_type = std::function<bool(Params...)>;
};

template <typename ...Params>
void call2(typename func_traits<Params...>::func_type func) {}