C++ 函数模板和缩写函数模板之间的等价性
以下所有标准参考均指2020年6月22日生成的标准C++ 函数模板和缩写函数模板之间的等价性,c++,templates,language-lawyer,c++20,C++,Templates,Language Lawyer,C++20,以下所有标准参考均指2020年6月22日生成的标准 声明[摘录,强调我的]: 缩写函数模板是具有一个或多个通用参数类型占位符([dcl.spec.auto])的函数声明缩写函数模板相当于函数模板([temp.fct]),其模板参数列表包括函数声明的每个通用参数类型占位符的一个发明类型模板参数,,按出现顺序排列。[…] 这样,以下to函数声明就相当于: 现在,类型模板参数的名称不需要与函数模板的重新声明(或定义)一致,只需命名泛型类型占位符即可 GCC的错误消息特别有趣,暗示发明的类型模板参数被
声明[摘录,强调我的]: 缩写函数模板是具有一个或多个通用参数类型占位符([dcl.spec.auto])的函数声明缩写函数模板相当于函数模板([temp.fct]),其模板参数列表包括函数声明的每个通用参数类型占位符的一个发明类型模板参数,,按出现顺序排列。[…] 这样,以下to函数声明就相当于: 现在,类型模板参数的名称不需要与函数模板的重新声明(或定义)一致,只需命名泛型类型占位符即可 GCC的错误消息特别有趣,暗示发明的类型模板参数被视为具体类型,而不是泛型类型占位符 问题:
- 关于案例A1到D1(分别拒绝和接受),GCC和Clang中的哪一项是正确的?GCC和Clang拒绝上述案例是否正确?(工作草案的)哪一段标准段落明确支持它们
- 这是:
模板
无效e(T,自动);
换言之:
template<typename T, typename U>
void e(T, U);
模板
空位e(T,U);
相比之下,这:
模板
void e(auto,T){}
翻译为:
template <typename T, typename U>
void e(U, T) {}
模板
空位e(U,T){}
记住这一点。因此,由于颠倒了模板参数的顺序,这些参数没有声明相同的模板。第一个声明一个模板,第二个声明并定义一个不同的模板
您不会仅仅从中得到编译错误,因为第二个定义也是一个声明。但是,使用类成员时,成员外定义不是声明。因此,它们在成员声明中必须具有匹配项。他们没有;因此出现了错误
至于其他文本,“功能等同(但不等同)”文本是一种非规范性符号。您引用的实际规范性文本明确指出,这些是“等效的”,而不仅仅是“功能等效的”。由于术语“等价物”(per)用于匹配声明和定义,在我看来,该标准规定从A到D的情况都可以 奇怪的是,这个非规范性的文本是。但是,它继承了来自的
ConceptName auto
语法的建议
因此,就规范性文本而言,一切似乎都很清楚。但非规范性矛盾的存在表明规范中存在编辑问题或实际缺陷
虽然本标准本身在措辞上清晰且规范合理,但这似乎不是本标准作者的意图 介绍了“功能等效”的概念,将其与“等效”区分开来。这一建议被接受。然而,P0717是在采用C++20的概念TS的早期引入的。在该提案中,它特别提到了简洁的模板语法,EWG明确投票赞成采用“功能等效”的措辞,而不是“等效”的措辞 也就是说,P0717明确指出,委员会旨在要求用户使用一致的语法 然而,概念TS中简洁的模板语法已从C++20中删除(或者说,从未真正添加)。这意味着任何“功能对等”的措辞都不会出现,因为该功能从未出现过 然后P1141出现了,它添加了缩写的模板语法,这涵盖了概念TS简洁模板语法的大部分基础。但是,尽管P0717的作者之一是P1141的作者,显然有人在措辞上犯了错误,没有人发现。这就解释了为什么非规范性案文指出缺乏真正的对等:因为这实际上是委员会的意图
所以这很可能是规范性文本中的错误。啊,我明白了。根据这一推理,A1到D1(同样,A2到D2)的格式是否正确,因此GCC拒绝A1到D1是错误的?@dfri:我没有这么说。我只是说案例E肯定不匹配,为什么不匹配。也就是说,它们不是两种形式的“等价物”。是的,你是对的,对不起,在你的答案之外,你跳到了进一步的结论。我的解释是,示例A1到D1中的两个声明声明了相同的等效函数模板,因此GCC的当前负责人有一个bug/尚未完全符合w.r.t。此功能。@dfri:我添加了一些关于案例a到D的讨论。这肯定意味着功能等效,但不等效,但其意图已经足够明确,无论怎样,规范性文本都可能被编辑固定下来。参见中的基本原理,其中报告了EWG调查结果为15/14/13/2/3。
// A2: OK
struct Sa {
template <typename T>
void a(T);
};
void Sa::a(auto) {}
// B2: OK
struct Sb {
void b(auto);
};
template <typename T>
void Sb::b(T) {}
// C2: OK
struct Sc {
template <typename T, typename U>
void c(T, U);
};
void Sc::c(auto, auto) {}
// D2: OK
struct Sd {
template <typename T, typename U>
void d(T, U);
};
template <typename T>
void Sd::d(T, auto) {}
// E2: Error
struct Se {
template <typename T>
void e(T, auto);
};
template <typename T>
void Se::e(auto, T) {}
error: no declaration matches 'void Se::e(auto:7, T)'
note: candidate is:
'template<class T, class auto:6> void Se::e(T, auto:6)'
error: out-of-line definition of 'e' does not match
any declaration in 'Se'
template <typename T>
void e(T, auto);
template<typename T, typename U>
void e(T, U);
template <typename T>
void e(auto, T) {}
template <typename T, typename U>
void e(U, T) {}