Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
147 views
in Technique[技术] by (71.8m points)

c++ - Compiler variance for trailing requires-clauses on non-templated functions

Consider the following example:

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

Clang(1) (DEMO) accepts this program, whereas GCC(1) (DEMO) rejects it with the following error:

error: constraints on a non-templated function

Note that the constraint expression can actually be used in Clang's case, as the following program is rejected by Clang:

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

with Clang noting that that the declared f is not a candidate as the constraints were not satisfied (for it to be a candidate for the f() call; DEMO).

  • Which compiler is correct here, and what is(/are) the relevant standard rule(/s) that govern this?

(1) GCC HEAD 11.0.0 20210124 and Clang HEAD 12.0.0 (20210124), -std=c++20.

question from:https://stackoverflow.com/questions/65882929/compiler-variance-for-trailing-requires-clauses-on-non-templated-functions

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

All standard references below refer, unless noted otherwise, to N4861 (March 2020 post-Prague working draft/C++20 DIS).


This is a Clang bug, and GCC is correct to reject the program, as per [dcl.decl]/4 (as well as [temp.constr.decl]/1) [emphasis mine]:

The optional requires-clause in an init-declarator or member-declarator shall be present only if the declarator declares a templated function ([dcl.fct]). When present after a declarator, the requires-clause is called the trailing requires-clause. [...]

The same paragraph also contains a (non-normative) example explicitly pointing out the OP's example as ill-formed:

[ Example:

void f1(int a) requires true;       // error: non-templated function

template<typename T>
auto f2(T a) -> bool requires true; // OK

// ...

end example ]

We may note that in an earlier version of the (to become C++20) working draft, N4810, [dcl.decl]/4 had a weaker requirement for where requires-clauses were allowed to appear:

The optional requires-clause (Clause 13) in an init-declarator or member-declarator shall not be present when the declarator does not declare a function (9.2.3.5). [...]

[ Example:

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

// ...

end example ]

where the non-normative example of the use case of the OP was explicitly shown as well-formed. The original intent there was arguably to allow constraining of non-template member functions of class templates based on the template parameters of the class template:

#include <iostream>

template<bool B>
struct S {
    void f() requires   B  { std::cout << "true
"; }
    void f() requires (!B) { std::cout << "false
"; }
};

int main() { 
    S<true>{}.f();   // true
    S<false>{}.f();  // false
} 

this is still allowed in the final state (intended for C++20) of [dcl.decl]/4 in N4861, where the restriction is to that of a templated function (see templated entity in [temp.pre]/8, particularly [temp.pre]/8.3), which does not only cover function templates (and function template members of non-templates and template class templates), but also non-template member functions of class templates.


Clang bug report:


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...