C ++ - 围绕函数模板实例化的规则

时间:2011-12-09 16:19:45

标签: c++ templates function instantiation overloading

我刚刚学习函数模板,我想研究一下函数模板实例化的一些规则。所以我写了下面的代码:

#include <iostream>

template <typename>
int check(int x) {
  return x * 2;
}

int main() {
  std::cout << check<double>(10) << std::endl; // #1
  std::cout << check<>(10) << std::endl;         // #2
  std::cout << check(10) << std::endl;            // #3
  return 0;
}

第1行,第2行和第3行不是一起编译的,每次尝试我只留下其中一行并评论其余部分。 因此,当启用#1时,我没有编译错误,并且打印了正确答案“20”。据我了解,“check&lt;”double“&gt;”调用模板实例化机制,因此实际创建了“int check(int)”函数(模板参数的类型没有没有任何影响力。 当#3启用时,我有一个编译错误“错误:没有匹配函数来调用'check(int)'”,这是合理的,因为我试图调用“ check(int)“不存在的函数。我的问题是关于#2的情况:在这种情况下,我得到相同的“错误:没有匹配函数来调用'check(int)'”。不应该调用“check&lt;&gt;(10)”触发模板实例化机制吗?

5 个答案:

答案 0 :(得分:1)

您不会在&lt;&gt;中放置任何模板参数。编译器如何知道要实例化哪个模板函数?请注意您的模板功能是:

template <typename>
int check(int x) 

如果您将其更改为:

template <typename T>
int check(T x) 

然后检查&lt;&gt;(10)应该没问题,因为编译器可以从参数中知道类型。

答案 1 :(得分:0)

如果没有传递模板参数,它等同于在没有模板参数的情况下查找函数(即它不实例化模板)。添加的<>在这种情况下没有任何意义,因为没有重载。

由于你所拥有的函数实际上并没有将模板用于任何东西,因此编译器无法推断类型T,但如果你这样写:

template <typename T>
T check(T x) {
    return x * 2;
}

然后所有3个案例都可以使用,因为它推断出类型T。有关详细说明,请参阅https://stackoverflow.com/a/797632/888641

注意:您可以使用typenameclass,他们会在此处执行完全相同的操作。

答案 2 :(得分:0)

我不得不说通常模板不会这样:(

试试这个:

template<typename T>
T check(T x){
    return x*2;
}

答案 3 :(得分:0)

如果可以推导出模板参数,

#2将是有效的。

#include <iostream>

template <class T>
void foo(T t)
{
    std::cout << "Template " << t << '\n';
}

void foo(int n)
{
    std::cout << "Not template " << n << '\n';
}

int main()
{
    foo(10); //calls non-template function 
             //because matching non-template preferred over function templates

    foo<>(10); //calls the template function, empty brackets indicate you want
               //the template overload, type is deduced from passed argument.

}

另一种可能性,如果函数模板具有默认参数(仅在C ++ 11中合法)。

template <class T = void>
int foo()
{
    return 10;
}

int main()
{
    return foo<>(); //same as foo<void>();
}

答案 4 :(得分:0)

您将获得的唯一模板实例化是

check<double>(10)

其他人不会实例化模板。此外,功能模板的全部功能还包括模板参数

template<typename T>
T check(T x) {
  return x*2;
}

然后使用模板参数推断的功能,您可以调用

check(10.0);   // instantiates check<dobule>
check(3);      // instantiates check<int>

a = MyObject();
check(a);         // instantiates check<MyObject>