代码之家  ›  专栏  ›  技术社区  ›  dfrib

非模板函数上尾部requires子句的编译器差异

  •  2
  • dfrib  · 技术社区  · 4 年前

    考虑下面的例子:

    void f() requires true { }
    int main() { f(); }
    

    叮当声 (1) ( DEMO )接受此程序,而GCC (1) ( DEMO )拒绝它,并出现以下错误:

    error: constraints on a non-templated function
    

    请注意,约束表达式实际上可以用于Clang的情况,因为Clang拒绝了以下程序:

    void f() requires false { }
    int main() { f(); }  //  // error: no matching function for call to 'f'
    

    叮当地说 f 由于约束条件未得到满足,因此不是候选人(因为它是 f() 呼叫 DEMO ).

    • 这里哪一个编译器是正确的,管理它的相关标准规则是什么?

    (1) GCC总目11.0.0 20210124和Clang总目12.0.0(20210124), -std=c++20 .

    1 回复  |  直到 4 年前
        1
  •  5
  •   cigien Jorge Eldis    4 年前

    除非另有说明,以下所有标准参考文件均指 N4861 (March 2020 post-Prague working draft/C++20 DIS) .


    这是一个叮当作响的错误,GCC根据 [dcl.decl]/4 (以及 [temp.constr.decl]/1 ) [ 强调 我的]:

    可选的 要求条款 在一个 初始化声明器 成员声明器 仅当声明器声明模板化函数时,才应出现 ([dcl.fct])。当出现在声明者之后时, 这个 要求条款 被称为 尾随要求从句 . [...]

    同一段还包含一个(非规范性)示例,明确指出OP的示例格式不正确:

    [ 例子:

    void f1(int a) requires true;       // error: non-templated function
    
    template<typename T>
    auto f2(T a) -> bool requires true; // OK
    
    // ...
    

    — 最后的例子 ]

    我们可能会注意到,在(将成为C++20)工作草案的早期版本中, N4810 ,[dcl.decl]/4对何处允许出现要求条款的要求较弱:

    可选的 要求条款 (第13条)在 初始化声明器 成员声明器 当声明器未声明函数时,不应出现(9.2.3.5)。[...]

    [ 例子:

    void f1(int a) requires true; // OK
    
    // ...
    

    — 最后的例子 ]

    其中OP用例的非规范性示例被明确显示为格式良好。其初衷可以说是允许基于类模板的模板参数约束类模板的非模板成员函数:

    #include <iostream>
    
    template<bool B>
    struct S {
        void f() requires   B  { std::cout << "true\n"; }
        void f() requires (!B) { std::cout << "false\n"; }
    };
    
    int main() { 
        S<true>{}.f();   // true
        S<false>{}.f();  // false
    } 
    

    在N4861中[dcl.decl]/4的最终状态(适用于C++20)中,这仍然是允许的,其中限制为 模板函数 (见 模板实体 在里面 [temp.pre]/8 尤其 [temp.pre]/8.3 ),不仅包括函数模板(以及非模板和模板类模板的函数模板成员),还包括类模板的非模板成员函数。


    叮当虫报告: