c++language-lawyerc++20requires-expression

Are types allowed to be specified for return-type-requirement in a requires expression?


Look at this simple concept example:

template <typename T>
requires requires(T t) { { t+t } -> bool; }
void fn() {
}

int main() {
    fn<bool>();
}

Here, I used bool as the type-constraint of return-type-requirement. The current draft says:

type-constraint:

nested-name-specifier opt concept-name

nested-name-specifier opt concept-name < template-argument-list opt >

So type-constraint must be a concept-name. Is bool (or any type) allowed as a concept name? If yes, what does it mean, and where does the draft standard allow it? I'd think that as bool is not a concept, so this is not allowed. Yet, both gcc and clang compile my example: godbolt

(Of course, it makes sense to allow types, I just don't see where the standard allows this, and what it means exactly: should types match exactly? Or conversions can happen?)


Solution

  • Is bool (or any type) allowed as a concept name?

    No, bool (or any type) are not concepts. They are types.

    The original design, and the Concepts TS, did allow types. That is, you could write a compound requirement like:

    { E } -> int;
    

    But this was removed from C++20 by P1452R2. There were a number of reasons this was removed, one of the motivations being what it would interfere with a future direction of wanting to adopt a generalized form of auto, like vector<auto> or vector<Concept>.

    What the type requirement allowed you to express, you already can anyway, by whichever of:

    { E } -> std::same_as<int>;
    { E } -> std::convertible_to<int>;
    

    was intended. Which also answers your question of what the type requirement actually meant - matching exactly or allowing conversions.