模板专业化和参考

Enr*_*lis 8 c++ reference template-specialization template-meta-programming c++14

C++ 中的函数式编程中,第 11 章涉及一些基本的模板元编程。

在这种情况下,作者展示了remove_reference/ 的这种实现remove_reference_t,它与cppreference 中描述的那些实现基本相同。

template<typename T> struct remove_reference      { using type = T; };
template<typename T> struct remove_reference<T&>  { using type = T; };
template<typename T> struct remove_reference<T&&> { using type = T; };
template<typename T> using remove_reference_t = typename remove_reference<T>::type;
Run Code Online (Sandbox Code Playgroud)

参考上面的代码,作者评论说,在“调用”时remove_reference_t<int>,只有general(或primary?这里的正确词是什么?)模板成功替代T,其他两个失败。这对我来说很清楚,没有办法int可以写成/匹配T&T&&

remove_reference_t<int&>然而,关于,作者说第二个专业无法匹配。好吧,由于引用折叠,它不能匹配吗?我的意思是,如果我替换为,则无法T&&匹配,从而得到?int&Tint&int&&& == int&

同样,在调用 时remove_reference_t<int&&>,不能将第一个专业化的T&匹配int&&ifT替换为int&(为什么我认为这& &会崩溃&&而不是&?)

是什么让编译器放弃一种专业化?

asc*_*ler 5

只有一般(或主要?这里的正确词是什么?)模板

C++ 标准使用的技术术语是“主类模板”。与它的部分特化和显式特化相比,它也将是最通用的类​​模板。因此,如果有足够的上下文,这也可能是一个合理的称呼。

“引用折叠规则”可在[dcl.ref]/6中找到,主要适用于确定将引用类型与通常形成对类型名称的类型的引用的引用类型别名相结合的&特定类型名称的含义时。为or&&形式的模板参数推导模板参数与此相反。尽管将模板参数推导视为“查找模板参数以使结果类型匹配”很有帮助,但模板参数推导的技术细节要具体得多;[temp.deduct]是几页规则,详细说明了如何进行扣除,并且其他部分还有其他相关规则。需要详细信息,以便编译器就可能存在多个“正确”答案的情况达成一致,并且编译器不需要处理一些更困难的情况。T&T&&

特别是,当将依赖类型P与已知类型匹配时,通过[temp.deduct.type]/8A中的可推导类型列表,如果 和都具有形式或两者都具有形式 ,则可以发生推导。当尝试部分特化的参数推导以确定、is和is 的定义时,因此它们不共享这些形式之一。PAT&T&&remove_reference<T&&>remove_reference<int&>PT&&Aint&

模板参数推导规则不一般允许从引用折叠规则的反向推导参数。但它们确实有一个与某些情况相关的有限允许:根据[temp.deduct.call]/3,如果T是模板类型参数,但不是类模板的参数,则该类型T&&是转发引用。在比较类型进行参数推导时,如果P=T&&是转发引用类型并且A是左值引用类型,则模板类型参数T可以被推导为左值引用类型A,只有当A是左值函数参数表达式的类型 ([temp.deduct .call]/3 )或者有时 ifPA被比较,因为它们代表两个比较函数类型([temp.deduct.type]/10)内的函数参数类型。

同样,当 ["]calling["] 时remove_reference_t<int&&>,第一个专业化的if不能T&匹配吗?int&&TT&

在这种情况下,部分特化不可能remove_reference<T&>匹配remove_reference<int&&>。即使模板参数推导过程允许找到这种情况的潜在答案,也不存在TT&相同的可能类型int&&