为什么下面的类模板匹配不模棱两可
Why is the following class template matching not ambiguous?
#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_func
重载犹豫不决时,可以毫不费力地消除对is_rvalue_ref
调用的歧义:
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]
对于两个类模板部分专用化,第一个至少是 与第二个 if 一样专业,给定以下重写为两个 函数模板,第一个函数模板至少为 根据功能的排序规则专门作为第二 模板 (14.5.6.2(:
— 第一个函数模板具有相同的 模板参数作为第一个部分专用化,并具有 类型为类模板的单个函数参数 使用第一个部分的模板参数进行专用化 专业化,以及
— 第二个函数模板具有相同的 模板参数作为第二个部分专用化,并具有 类型为类模板的单个函数参数 使用第二个部分的模板参数进行专用化 专业化。
在上面的示例中,is_rvalue_ref_func
重载是通过精确地执行is_rvalue_ref
主模板的重写和部分专用化来获得的。为什么函数调用不明确,但类模板匹配定义良好?
如果匹配,则会自动优先于主要专业化。[temp.class.spec.match]/1:
当类模板在需要 实例化类时,有必要确定是否 实例化将使用主模板或以下模板之一生成 部分专业化。这是通过匹配模板来完成的 类模板专用化与模板的参数 部分专业化的参数列表。
(1.1( — 如果正好找到一个匹配的专业化,则 实例化是从该专用化生成的。
对于函数调用,部分排序启动 - 并且为了参数推导的目的,它忽略了引用,[temp.deduct.partial]/5:
在完成部分排序之前,某些转换是 对用于部分排序的类型执行:
(5.1( — 如果
P
是引用类型,则P
替换为该类型 提到。
。这使得函数模板等效于部分排序。因此,该呼吁是模棱两可的。
在上面的示例中,
is_rvalue_ref_func
重载由下式获得 精确地执行is_rvalue_ref
主数据库的重写 模板和部分专业化。
几乎不。
第一个函数模板具有与 第一个部分专用化,并且具有单个函数参数,其 类型是具有模板参数的类模板专用化 第一个部分专业化
给定类模板template<class> class SomeTemplate;
,正确的重写是
template<class T> void is_rvalue_ref_func(SomeTemplate<T>);
template<class T> void is_rvalue_ref_func(SomeTemplate<T&&>);
函数模板不是部分专用的。您的报价仅适用于部分类模板专用化。它使用函数重载解析的规则来定义哪个专用化更专用。
相反,函数模板是重载的,并且有两个同样好的重载。请注意,您不能部分专化函数模板,只能完全专化它们。
如果你想使用函数模板来确定某物是否是右值,你可以做这样的事情(我认为;目前我不能轻易测试代码(:
template <typename T>
constexpr bool is_rvalue_func(T&&) {
return !std::is_reference<T>::value;
}
不过,我认为您无法区分传递给函数的右值和右值引用。也就是说,我认为这两者都会产生true
尽管只有后者实际上是对对象的右值引用:
is_rvalue_func(int());
int i(17);
is_rvalue_func(std:move(i));
- 为什么对模板的调用不模棱两可?
- 为什么同时覆盖全局新运算符和特定于类的运算符不是模棱两可的行为?
- 为什么编译器不给出模棱两可的参考错误
- 为什么我在单独的命名空间中转发到 std::make_pair 模棱两可
- 为什么此C++代码中的构造函数模棱两可以及如何修复它
- 为什么运算符<<是模棱两可的?
- 为什么这个呼吁会员函数模棱两可
- 为什么这会导致模棱两可的模板错误
- 如果铸造运算符对类型和引用类型的引用,为什么直接列表初始化会导致类型参考铸件的模棱两可
- 为什么命名空间内的自由功能模棱两可
- 为什么对函数的调用"sample_mean"模棱两可的?
- 没有函数重写的多重继承.为什么模棱两可
- 为什么下面的类模板匹配不模棱两可
- 为什么下面的运算符重载是模棱两可的
- 模棱两可的重载函数 - 如何以及为什么
- C++ 为什么电话模棱两可
- 为什么是模棱两可的,以及如何避免它
- 为什么我的程序对wstring错误给出模棱两可的引用?
- 为什么我的 T& 和 T&& copy 构造函数模棱两可?
- 为什么这些重载不模棱两可?