繁体   English   中英

function 模板和缩写 function 模板之间的等效性

[英]Equivalence between function templates and abbreviated function templates

以下所有标准参考均指当前的 ISO 标准工作草案,于 2020 年 6 月 22 日生成。


[dcl.fct]/18指出[摘录,强调我的]:

缩写的 function 模板是具有一个或多个通用参数类型占位符 ([dcl.spec.auto]) 的 function 声明。 An abbreviated function template is equivalent to a function template ([temp.fct]) whose template-parameter-list includes one invented type template-parameter for each generic parameter type placeholder of the function declaration, in order of appearance. [...]

这样 function 声明的以下内容可能是等效的:

template <typename T>
void f(T);

void f(auto);  // re-declaration

然而,我们可能会注意到, [dcl.fct]/18的例子表明

[...]

这些声明在功能上等同于但不等同于)以下声明。

[...]

可以说(我不确定如何解释这一点)与前面段落中的等价陈述相冲突。

Now, both GCC 10.1.0 and Clang 10.0.0 (as well as GCC:HEAD and Clang:HEAD) have some mixed behavior here. If we declare a function template and later define it (/re-declare it) using a mixed classical function template syntax with abbreviated function template syntax, Clang accepts most cases (defining a previously declared function) whereas GCC rejects all (sees the (attempted ) 重新声明为单独声明的函数,随后在重载解析中出现歧义失败):

// A1: Clang OK, GCC error
template <typename T>
void a(T);

void a(auto) {}

// B1: Clang OK, GCC error
void b(auto);

template <typename T>
void b(T) {}

// C1: Clang OK, GCC error
template <typename T, typename U>
void c(T, U);

void c(auto, auto) {}

// D1: Clang OK, GCC error
template <typename T, typename U>
void d(T, U);

template <typename T>
void d(T, auto) {}

// E1: Clang error, GCC error
template <typename T>
void e(T, auto);

template <typename T>
void e(auto, T) {}

int main() {
    a(0);      // Clang OK, GCC error.
    b(0);      // Clang OK, GCC error.
    c(0, '0'); // Clang OK, GCC error.
    d(0, '0'); // Clang OK, GCC error.
    e(0, '0'); // Clang error, GCC error.
}

Curiously, if we make the function template a class member function template, both GCC and Clang accepts cases A1 through D1 , but both rejects the final case E1 above:

// 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) {}

带有以下错误消息:

GCC

 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)'

Clang

 error: out-of-line definition of 'e' does not match any declaration in 'Se'

现在,类型模板参数的名称不需要与 function 模板的重新声明(或定义)保持一致,只需命名通用类型占位符即可。

GCC 的错误消息特别有趣,暗示发明的类型模板参数被视为具体类型而不是泛型类型占位符。

问题:

  • GCC 和 Clang 中的哪一个对于案例A1D1是正确的(分别为拒绝和接受)? GCC 和 Clang 是否正确拒绝上述案例E2 什么标准段落(工作草案)明确支持他们?

这个:

 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) {}

请记住,缩写的 function 模板参数放在模板参数列表的末尾 因此,由于颠倒了模板参数的顺序,它们并没有声明相同的模板。 第一个声明一个模板,第二个声明并定义一个不同的模板。

您不会因此而得到编译错误,因为第二个定义也是一个声明。 但是,当您使用 class 成员时,成员外定义不是声明 因此,它们必须具有匹配的成员内声明。 他们没有; 因此错误。


至于其他,“功能等效(但不等效)”文本是非规范性符号。 您引用的实际规范性文本明确指出这些是“等效的”,而不仅仅是“功能等效”。 而且由于根据[temp.over.link]/7的术语“等效”用于匹配声明和定义,因此在我看来,标准规定 A 到 D 的情况很好。

奇怪的是,这个非规范性文本是由引入规范性文本的同一提案引入的 但是,它继承了ConceptName auto语法的提议似乎很清楚,它意味着“等效”,而不是“功能等效”

因此,就规范性文本而言,一切似乎都很清楚。 但是,非规范性矛盾的存在表明存在编辑问题或规范中的实际缺陷。


虽然标准本身在措辞方面是明确的并且在规范上是合理的,但这似乎不是标准作者的意图

P0717引入了“功能等效”的概念,以区别于“等效”。 该提议被接受。 但是,P0717 是在采用 C++20 的概念 TS 的早期引入的。 在该提案中,它特别谈到了简洁的模板语法,并且 EWG 明确投票赞成采用“功能等效”的措辞,而不是概念 TS 的“等效”措辞。

也就是说,P0717 明确指出,委员会打算要求用户使用一致的语法。

但是,Concepts TS 中的简洁模板语法已从 C++20 中删除(或者更确切地说,从未真正添加)。 这意味着任何“功能等效”的措辞都从未出现过,因为该功能从未出现过。

然后发生了 P1141,它添加了缩写模板语法,涵盖了 Concepts TS 简洁模板语法的大部分基础。 但是,尽管 P0717 的作者之一是 P1141 的作者,但显然有人在措辞上犯了错误,没有人注意到它。 这可以解释为什么非规范性文本指出缺乏真正的对等:因为这实际上是委员会的意图。

因此,这很可能是规范性文本中的错误。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM