c++ - 为什么下面的类模板匹配不二义?

标签 c++ templates c++11

#include <iostream>
#include <utility>

template <class T> struct is_rvalue_ref      : std::false_type {};
template <class T> struct is_rvalue_ref<T&&> : std::true_type {};

template <typename T> bool is_rvalue_ref_func(T){return false;}
template <typename T> bool is_rvalue_ref_func(T&&){return true;}

class A {};

int main() 
{
  std::cout << std::boolalpha;
  std::cout << is_rvalue_ref<A>::value << '\n';
  std::cout << is_rvalue_ref<A&>::value << '\n';
  std::cout << is_rvalue_ref<A&&>::value << '\n';

  /*****THIS FAILS TO COMPILE************
  A a;
  A& alv = a;
  A&& arv = std::move(a);
  std::cout << is_rvalue_ref_func(a) << '\n';
  std::cout << is_rvalue_ref_func(alv) << '\n';
  std::cout << is_rvalue_ref_func(arv) << '\n';
  **************************************/   

  return 0;
}

编译器 (clang 3.5 -std=c++11) 可以毫不费力地消除对 is_rvalue_ref 的调用的歧义,同时它对 is_rvalue_ref_func 犹豫不决> 重载:

rv.cpp:31:16: error: call to 'is_rvalue_ref_func' is ambiguous
  std::cout << is_rvalue_ref_func(a) << '\n';
               ^~~~~~~~~~~~~~~~~~
rv.cpp:8:6: note: candidate function [with T = A]
bool is_rvalue_ref_func(T)
     ^
rv.cpp:14:6: note: candidate function [with T = A &]
bool is_rvalue_ref_func(T&&)
     ^
rv.cpp:32:16: error: call to 'is_rvalue_ref_func' is ambiguous
  std::cout << is_rvalue_ref_func(alv) << '\n';
               ^~~~~~~~~~~~~~~~~~
rv.cpp:8:6: note: candidate function [with T = A]
bool is_rvalue_ref_func(T)
     ^
rv.cpp:14:6: note: candidate function [with T = A &]
bool is_rvalue_ref_func(T&&)
     ^
rv.cpp:33:16: error: call to 'is_rvalue_ref_func' is ambiguous
  std::cout << is_rvalue_ref_func(arv) << '\n';
               ^~~~~~~~~~~~~~~~~~
rv.cpp:8:6: note: candidate function [with T = A]
bool is_rvalue_ref_func(T)
     ^
rv.cpp:14:6: note: candidate function [with T = A &]
bool is_rvalue_ref_func(T&&)
     ^
3 errors generated.

但是,根据14.5.5.2 [temp.class.order]

For two class template partial specializations, the first is at least as specialized as the second if, given the following rewrite to two function templates, the first function template is at least as specialized as the second according to the ordering rules for function templates (14.5.6.2):

— the first function template has the same template parameters as the first partial specialization and has a single function parameter whose type is a class template specialization with the template arguments of the first partial specialization, and

— the second function template has the same template parameters as the second partial specialization and has a single function parameter whose type is a class template specialization with the template arguments of the second partial specialization.

在上面的示例中,is_rvalue_ref_func 重载是通过对 is_rvalue_ref 主模板和部分特化的精确重写获得的。为什么函数调用不明确但类模板匹配定义明确?

最佳答案

如果匹配,部分特化会自动优先于主要特化。 [temp.class.spec.match]/1:

When a class template is used in a context that requires an instantiation of the class, it is necessary to determine whether the instantiation is to be generated using the primary template or one of the partial specializations. This is done by matching the template arguments of the class template specialization with the template argument lists of the partial specializations.

(1.1) — If exactly one matching specialization is found, the instantiation is generated from that specialization.

对于函数调用,部分排序开始了 - 它忽略了参数推导目的的引用,[temp.deduct.partial]/5:

Before the partial ordering is done, certain transformations are performed on the types used for partial ordering:

(5.1) — If P is a reference type, P is replaced by the type referred to.

... 这使得函数模板等同于部分排序。因此调用是不明确的。

关于c++ - 为什么下面的类模板匹配不二义?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28519704/

相关文章:

java - 在 C++ 或 Java 中有没有办法获得 CPU 使用率?

C++ 17 元编程递归结构 : enum or constexpr

c++ - 调用模板函数时的意外输出

c++ - 使用 CPR 从 C++ 调用 HTTP?

c++ - 找到最接近另一个数字的数字c++

c++ - 为什么我的 C++ 代码显示段错误

c++ - 如何在模板函数或类中实例化包含类型的容器变量?

C++ 将模板类型作为参数传递给错误

c++ - 在循环中创建和填充 vector

c++ - 根据枚举成员的值特化模板