将调用两个重载模板中的哪一个?

时间:2012-08-01 08:34:42

标签: c++ templates function-templates

我仍在尝试找出模板。我已经阅读了有关专业化规则的内容,并且不明白这里发生了什么。

我在templates.h中定义了以下内容:

#include <iostream>

template <typename foo>
void f(foo p)
{
  std::cout << "one" << std::endl;
}

template <typename bar>
void f(int p)
{
  std::cout << "two" << std::endl;
}

现在,如果我包含这个并在我的主要中像这样调用它

  f(1);
  f("x");

我得到了

one
one

现在的问题是,为什么第一个比第二个更具体是针对整数?我觉得它至少应该是模棱两可的,根本不起作用。

4 个答案:

答案 0 :(得分:5)

首先,您没有专业化,而是两个独立的,无关的重载

其次,第二个重载通常是不可行的,因为您在没有模板参数的情况下调用该函数,因此无法推导出模板参数bar。因此,只有第一次过载是可行的,并且可以使用。


实际的专业化将如下所示:

template <>
void f<int>(int p) { /* ... */ }

更好的是,坚持使用重载(通常更好地重载函数而不是提供模板特化),但是将第二个作为非模板:

void f(int p) { /* ... */ }

答案 1 :(得分:4)

第二个重载没有模板对函数参数的依赖,所以你必须这样调用它:

f<std::string>(1);
f<double>(42);
f<SomeType>(1);

拥有第二个版本是否有意义是另一回事。你可以想象有一个的模板参数对函数的内部逻辑有一些影响:

template <typename SomeType>
int foo(int seed) {
  // instantiate a SomeType and use it to calculate return value
};

int i = foo<Type1>(42);
int j = foo<Type2>(42);

另一方面,您的SomeType可能是一个函数参数:

template <typename SomeType>
int foo(int seed, const SomeType& s) {
  // use s to calculate return value
};

Type1 t1;
Type2 t2;
int i = foo(42, t1);
int j = foo(42, t2);

答案 2 :(得分:1)

在第二个bar中无法从函数参数中推导出来,并且必须明确给出:

f<whatever>(1);

答案 3 :(得分:0)

打印&#34;两个&#34;不被认为是明确的专业化。试试这个

template <>
void f(int p)
{
  std::cout << "two" << std::endl;
}