c++ - 为什么函数重载有歧义,而模板重载却没有歧义?

标签 c++ templates overload-resolution

<分区>

为什么,在下面,调用了 bar 的实例化?没有歧义,而非模板重载函数foo是模棱两可的。 nullptr也是一样的而不是 NULL

#include <iostream>

template<typename T>
void bar (T*)
{
  std::cout << "bar(T*)" << std::endl;
}

template<typename T>
void bar (typename T::value_type *)
{
  std::cout << "bar(T::value_type*)" << std::endl;
}

struct A
{
  using value_type = int;
};

void foo (A::value_type*)
{
  std::cout << "foo(A::value_type *)" << std::endl; 
}

void foo (A*)
{
  std::cout << "foo(A *)" << std::endl; 
}

int main ()
{
  bar<A> (NULL);
  foo (NULL); // ambigous
}

编辑:要清楚。我期待 foo过载是模棱两可的。我不明白为什么 bar实例化 bar<A> 时生成的重载不是同样模棱两可。

最佳答案

确定哪个过载是最后一个决胜局的最佳可行候选者的规则包括,来自 [over.match.best]:

Given these definitions, a viable function F1 is defined to be a better function than another viable function F2 if for all arguments i, ICSi(F1) is not a worse conversion sequence than ICSi(F2), and then
— [...]
— F1 and F2 are function template specializations, and the function template for F1 is more specialized than the template for F2 according to the partial ordering rules described in 14.5.6.2.

只有当我们有两个具有相同转换序列的函数并且其中一个是或都不是函数模板时,才会达到该要点。对于 foo,我们的两个重载候选者都具有相同的转换序列,函数模板也不是,最后一个要点不适用 - 所以它是模棱两可的。

不过,对于 bar,我们可以尝试看看是否有一个

template<typename T> void bar (T*) // (1)
template<typename T> void bar (typename T::value_type *) // (2)

比另一个更专业。其规则基本上是尝试查看是否可以使用另一个参数调用一个函数。在这种情况下,任何 typename T::value_type* 仍然是一个指针,因此您可以用它调用 T* 重载。然而,在另一个方向上,模板推导将失败,因为 typename T::value_type 是一个非推导的上下文。因此 (2) 被认为是部分特化的,因此它被选为最佳可行候选者。没有歧义。

关于c++ - 为什么函数重载有歧义,而模板重载却没有歧义?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31520540/

相关文章:

android - 带有 ubuntu 索引器的 C/C++ IDE

c++ - 单个应用程序 C++ 的多个控制台

c# - C# 4 中的重载分辨率和可选参数

c# - 使用变体通用委托(delegate)类型对运算符 == 的重载解析

Swift:泛型重载, "more specialized"的定义

c++ - 在cpp中格式化

c++ - 如何在 BGL 中按照(捆绑)属性提供的顺序迭代顶点和边?

c++ - 根据模板参数选择宏定义

c++ - 你能在 C++ 元编程中做文件 IO 吗?

c++ - "Manual"签名重载解析