如果我没有理解错的话,类模板定义了一个函数,所以当我调用时,编译器有可能进行隐式强制转换,但是在函数模板的情况下,此时没有函数定义,所以隐式强制转换不会发生。
但我不明白为什么编译器不能创建函数定义,然后应用隐式强制转换?
#include <functional>
template<typename ...ARGS>
class Test1
{
public:
void add(const std::function<void(ARGS...)>&) {}
};
class Test2
{
public:
template<typename ...ARGS>
void add(const std::function<void(ARGS...)>&) {}
};
void func(int) {}
int main()
{
Test1<int> test1;
test1.add(func);
Test2 test2;
test2.add<int>(func);
}
错误是:
在函数“int main()”中:
25:24:错误:调用“test2::add(void(&)(int))”没有匹配函数
25:24:注:候选人是:
14:10:注意:模板void test2::add(const std::function&)
14:10:注:模板参数推演/替换失败:
25:24:注意:类型“const std::function”和“void(int)”不匹配
在第一种情况下,您是显式实例化类模板test1
。这意味着其add
成员的函数声明是用签名add(const std::function
生成的。当编译器随后尝试解析test1.add(func)
时,只有一个候选项。由于std::function
可以由void(int)
函数隐式构造,签名匹配,编译器只需实例化成员函数定义,一切都很好。
在第二种情况下,编译器不得不执行模板参数推导/替换,以查看是否可以“使用”add
模板。您可能认为指定int
会确定模板参数,这样就不需要进行任何推导,但事实并非如此:可能您的意思是部分指定模板参数,请参见此处的示例。换句话说,您可能试图使用比您显式指定的更多的参数实例化函数模板,至少编译器不知道您是否这样做。因此,它仍然必须尝试匹配std::function
(或者更准确地说,std::function
和void(int)
的类型,它不能匹配这些类型,因为不考虑隐式转换进行推导。
简而言之:指定显式模板参数并不阻止variadic函数模板的模板参数推导。
注意:我不是100%与确切的术语坚定,任何语言律师纠正我是赞赏的!
编辑:我主要基于我在这里读到的内容。
假设有一个模板函数 接受任意数量的参数。给定最后一个参数始终是 ,我如何实现下面显示的 模板,以便 包含此 的参数? 例如,如果像这样调用,应该是: 我的第一个想法是: 但这不会编译: 问题一: 为什么这不能编译?为什么模板参数演绎失败? 最终,我想出了这个解决方案: 这里,是,即中的最后一种类型。然后,的临时值被传递到,其中。这行得通,但在我看来很难看。 问题二: 我想知道如果没有两个函数和的临
在C++11之前,类模板和函数模板只能含有固定数量的模板参数。C++11增强了模板功能,允许模板定义中包含0到任意个模板参数,这就是可变参数模板。可变参数模板的加入使得C++11的功能变得更加强大,而由此也带来了许多神奇的用法。 可变参数模板 可变参数模板和普通模板的语义是一样的,只是写法上稍有区别,声明可变参数模板时需要在typename或class后面带上省略号...: template<ty
使用以下代码生成时 生成以下诊断(代码后): 诊断: 有趣的部分不是关于歧义错误本身(这不是这里主要关注的问题)。有趣的是,当仅使用函数名调用fun时,第一个fun的模板参数F被解析为纯函数类型double(double),而第二个fun的模板参数F被解析为更期望的函数指针类型。 然而,当我们将调用<代码>乐趣(测试) 更改为<代码>乐趣( 这种行为似乎是所有Clang和GCC(以及Visual
我有这样的情况 这是我自己的Vector类,构造函数模拟了Vector的行为(u可以通过使用interator提供的数据范围来构造它),但增加了一个要求,即容器是与正在构造的容器相同类型的模板。我有错误 5.cpp:16:36:错误:调用“Vector::Vector(Vector::Iterator,Vector::Iterator)”没有匹配函数5.cpp:16:36:注意:候选项是:包含在5
std=C14的g在函子类的模板方法(本身不是模板)上给我一个“无法推断模板参数'Key'”错误。我不知道为什么。代码看起来应该可以工作。 我正在实现一个2-3树,它有一个采用函子的层次顺序遍历方法。操作人员tree23代码基本上是这样的: 级别顺序遍历调用仿函数的函数调用操作符,向其传递两个参数。 函子非常简单:
我目前有一个,但是为了灵活性,我希望能够分配一个lambda表达式,将作为映射中的值返回。 所以我创建了这个模板类: 并像这样使用它: IntelliSense提供了更多信息: 多个操作符“=”匹配这些操作数:function“valueorfunction::operator=(const std::function&other)[with T=std::wstring]”function“va