模板专业化和参考

Template specialization and references

Functional programming in 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;

参考上面的代码,作者评论说,在“调用”remove_reference_t<int>时,只有通用(或初级?这里的correcto词是什么?)模板成功替换T,另外两个失败了。这对我来说很清楚,int 不可能写成 as/matched 而不是 T&T&&.

但是,关于remove_reference_t<int&>,作者说二专不能匹配。好吧,由于参考崩溃,它不能匹配吗?我的意思是,如果我用 T 代替 int&T&& 不能匹配 int&,从而得到 int&&& == int&?

类似地,当调用remove_reference_t<int&&>时,第一个特化的T&不能匹配int&&如果T被替换为int&?(为什么我认为 & & 会崩溃为 && 而不是 &?)

是什么让编译器放弃了一种特化?

only the general (or primary? What is the correcto word here?) template

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

[dcl.ref]/6 and applies mainly when determining the meaning of combining a specific type name which aliases a reference type with a & or && token which would normally form a reference to the type name's type. Deducing template arguments for a template parameter of the form T& or T&& is sort of the reverse of that. Although it's helpful to think of template argument deduction as "find the template arguments so that the resulting types match up", the technical details of template argument deduction are much more specific; [temp.deduct]中找到的“引用折叠规则”是几页规则,具体说明了这个推导是如何进行的,其他部分还有额外的相关规则。需要详细信息,以便编译器在可能存在多个“正确”答案的情况下达成一致,这样编译器就不需要处理一些更困难的情况。

特别是,当根据 [temp.deduct.type]/8 中的可推导类型列表将依赖类型 P 与已知类型 A 匹配时,如果两者 PA 具有 T& 的形式,或者如果两者都具有 T&& 的形式。当尝试对偏特化 remove_reference<T&&> 进行参数推导以确定 remove_reference<int&> 的定义时,PT&&Aint&,所以他们不要共享其中一种形式。

模板参数推导规则不允许从引用折叠规则的反向推导参数。但他们确实有与某些情况相关的有限津贴:Per [temp.deduct.call]/3, if T is a template type parameter, but not a parameter for a class template, then the type T&& is a forwarding reference. When comparing types for argument deduction, if P=T&& is a forwarding reference type and A is an lvalue reference type, then the template type parameter T can be deduced as the lvalue reference type A, only if A is the type of an lvalue function argument expression ([temp.deduct.call]/3 again) or sometimes if P and A are being compared because they represent function parameter types within two compared function types ([temp.deduct.type]/10).

Similarly, when ["]calling["] remove_reference_t<int&&>, can't the first specialization's T& match int&& if T is substituted for T&?

在这种情况下,偏特化 remove_reference<T&> 无法匹配 remove_reference<int&&>。即使模板参数推导过程允许找到这种情况的潜在答案,也没有可能的类型 T 使得 T&int&&.

相同