I was playing around with C++ concepts and function overloading in a context completely removed from any templates, and stumbled upon this:
struct S { int mult(int x) requires (true) { return x; } int mult(int x) requires (false) { return x * 2; } }; int main() { std::cout << S{}.mult(5) << std::endl; }
g++ 11 refuses to compile this snippet because requires
-clauses may not be attached to non-template functions.
clang++ 13 is, however, fine with this snippet, but surprisingly spits out 10
instead of the 5
that I expected.
I know that the C++20 standard has only recently come out of the oven, so I completely understand that there are many issues to be worked out regarding concepts.
Disregarding the apparent uselessness of constant literal concepts, my question is: Are programs with requires
-clauses which are always false
ill-formed, possibly without requiring a diagnostic? Or, perhaps, is what I have not even legal C++ at all, as g++ is saying?
These are the two first examples in the "trailing requires-clause" section of the standard:
void f1(int a) requires true; // error: non-templated function template<typename T> auto f2(T a) -> bool requires true; // OK
Although examples given in the standard are explicitly non-normative, these make the intent abundantly clear.
Essentially, concepts can only be applied to template functions (so your code is invalid C++), but Boolean literals (e.g., requires true
) are perfectly valid.
However, templates whose requirements are never satisfied (whether by a literal false
in a required
clause or otherwise) seem to be ill-formed, as indicated by this example,
Your snippet is not legal C++.
[dcl.decl.general]
4 The optional requires-clause ([temp.pre]) 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. [...]
Since there isn't a template in sight (and no room to discuss if the mult
overloads are templated functions), your attempt is plain ill-formed. It's a "shall" requirement of a diagnosable rule.
So GCC is correct. Clang is doubly wrong to call a completely unintuitive overload. Though it really went of the rails when it accepted the program to being with.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With