Why do we require requires requires?












146















One of the corners of C++20 concepts is that there are certain situations in which you have to write requires requires. For instance, this example from [expr.prim.req]/3:




A requires-expression can also be used in a requires-clause ([temp]) as a way of writing ad hoc constraints on template arguments such as the one below:



template<typename T>
requires requires (T x) { x + x; }
T add(T a, T b) { return a + b; }


The first requires introduces the requires-clause, and the second introduces the requires-expression.




What is the technical reason behind needing that second requires keyword? Why can't we just allow writing:



template<typename T>
requires (T x) { x + x; }
T add(T a, T b) { return a + b; }


(Note: please don't answer that the grammar requires it)










share|improve this question




















  • 22





    Suggestion: "Is there anything that requires requires requires?". More seriously, I have a hunch that it's the same reason behind noexcept(noexcept(...)).

    – Quentin
    Jan 15 at 14:41








  • 10





    The two requires are homonyms in my opinion: they look the same, spell the same, smell the same, but are intrinsically different. If I were to suggest a fix, I'd suggest to rename one of them.

    – YSC
    Jan 15 at 14:59






  • 4





    @YSC - co_requires? (Sorry, couldn't resist).

    – StoryTeller
    Jan 15 at 15:25






  • 113





    Where will the madness stop? Next thing you know, we'll have long long.

    – Eljay
    Jan 15 at 15:25






  • 8





    @StoryTeller: "Requires requires required?" would have been even more alliterative!!

    – P.W
    Jan 15 at 15:43
















146















One of the corners of C++20 concepts is that there are certain situations in which you have to write requires requires. For instance, this example from [expr.prim.req]/3:




A requires-expression can also be used in a requires-clause ([temp]) as a way of writing ad hoc constraints on template arguments such as the one below:



template<typename T>
requires requires (T x) { x + x; }
T add(T a, T b) { return a + b; }


The first requires introduces the requires-clause, and the second introduces the requires-expression.




What is the technical reason behind needing that second requires keyword? Why can't we just allow writing:



template<typename T>
requires (T x) { x + x; }
T add(T a, T b) { return a + b; }


(Note: please don't answer that the grammar requires it)










share|improve this question




















  • 22





    Suggestion: "Is there anything that requires requires requires?". More seriously, I have a hunch that it's the same reason behind noexcept(noexcept(...)).

    – Quentin
    Jan 15 at 14:41








  • 10





    The two requires are homonyms in my opinion: they look the same, spell the same, smell the same, but are intrinsically different. If I were to suggest a fix, I'd suggest to rename one of them.

    – YSC
    Jan 15 at 14:59






  • 4





    @YSC - co_requires? (Sorry, couldn't resist).

    – StoryTeller
    Jan 15 at 15:25






  • 113





    Where will the madness stop? Next thing you know, we'll have long long.

    – Eljay
    Jan 15 at 15:25






  • 8





    @StoryTeller: "Requires requires required?" would have been even more alliterative!!

    – P.W
    Jan 15 at 15:43














146












146








146


17






One of the corners of C++20 concepts is that there are certain situations in which you have to write requires requires. For instance, this example from [expr.prim.req]/3:




A requires-expression can also be used in a requires-clause ([temp]) as a way of writing ad hoc constraints on template arguments such as the one below:



template<typename T>
requires requires (T x) { x + x; }
T add(T a, T b) { return a + b; }


The first requires introduces the requires-clause, and the second introduces the requires-expression.




What is the technical reason behind needing that second requires keyword? Why can't we just allow writing:



template<typename T>
requires (T x) { x + x; }
T add(T a, T b) { return a + b; }


(Note: please don't answer that the grammar requires it)










share|improve this question
















One of the corners of C++20 concepts is that there are certain situations in which you have to write requires requires. For instance, this example from [expr.prim.req]/3:




A requires-expression can also be used in a requires-clause ([temp]) as a way of writing ad hoc constraints on template arguments such as the one below:



template<typename T>
requires requires (T x) { x + x; }
T add(T a, T b) { return a + b; }


The first requires introduces the requires-clause, and the second introduces the requires-expression.




What is the technical reason behind needing that second requires keyword? Why can't we just allow writing:



template<typename T>
requires (T x) { x + x; }
T add(T a, T b) { return a + b; }


(Note: please don't answer that the grammar requires it)







c++ c++-concepts c++20






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Jan 15 at 19:31







Barry

















asked Jan 15 at 14:33









BarryBarry

181k19315576




181k19315576








  • 22





    Suggestion: "Is there anything that requires requires requires?". More seriously, I have a hunch that it's the same reason behind noexcept(noexcept(...)).

    – Quentin
    Jan 15 at 14:41








  • 10





    The two requires are homonyms in my opinion: they look the same, spell the same, smell the same, but are intrinsically different. If I were to suggest a fix, I'd suggest to rename one of them.

    – YSC
    Jan 15 at 14:59






  • 4





    @YSC - co_requires? (Sorry, couldn't resist).

    – StoryTeller
    Jan 15 at 15:25






  • 113





    Where will the madness stop? Next thing you know, we'll have long long.

    – Eljay
    Jan 15 at 15:25






  • 8





    @StoryTeller: "Requires requires required?" would have been even more alliterative!!

    – P.W
    Jan 15 at 15:43














  • 22





    Suggestion: "Is there anything that requires requires requires?". More seriously, I have a hunch that it's the same reason behind noexcept(noexcept(...)).

    – Quentin
    Jan 15 at 14:41








  • 10





    The two requires are homonyms in my opinion: they look the same, spell the same, smell the same, but are intrinsically different. If I were to suggest a fix, I'd suggest to rename one of them.

    – YSC
    Jan 15 at 14:59






  • 4





    @YSC - co_requires? (Sorry, couldn't resist).

    – StoryTeller
    Jan 15 at 15:25






  • 113





    Where will the madness stop? Next thing you know, we'll have long long.

    – Eljay
    Jan 15 at 15:25






  • 8





    @StoryTeller: "Requires requires required?" would have been even more alliterative!!

    – P.W
    Jan 15 at 15:43








22




22





Suggestion: "Is there anything that requires requires requires?". More seriously, I have a hunch that it's the same reason behind noexcept(noexcept(...)).

– Quentin
Jan 15 at 14:41







Suggestion: "Is there anything that requires requires requires?". More seriously, I have a hunch that it's the same reason behind noexcept(noexcept(...)).

– Quentin
Jan 15 at 14:41






10




10





The two requires are homonyms in my opinion: they look the same, spell the same, smell the same, but are intrinsically different. If I were to suggest a fix, I'd suggest to rename one of them.

– YSC
Jan 15 at 14:59





The two requires are homonyms in my opinion: they look the same, spell the same, smell the same, but are intrinsically different. If I were to suggest a fix, I'd suggest to rename one of them.

– YSC
Jan 15 at 14:59




4




4





@YSC - co_requires? (Sorry, couldn't resist).

– StoryTeller
Jan 15 at 15:25





@YSC - co_requires? (Sorry, couldn't resist).

– StoryTeller
Jan 15 at 15:25




113




113





Where will the madness stop? Next thing you know, we'll have long long.

– Eljay
Jan 15 at 15:25





Where will the madness stop? Next thing you know, we'll have long long.

– Eljay
Jan 15 at 15:25




8




8





@StoryTeller: "Requires requires required?" would have been even more alliterative!!

– P.W
Jan 15 at 15:43





@StoryTeller: "Requires requires required?" would have been even more alliterative!!

– P.W
Jan 15 at 15:43












5 Answers
5






active

oldest

votes


















72














It is because the grammar requires it. It does.



A requires constraint does not have to use a requires expression. It can use any more-or-less arbitrary boolean constant expression. Therefore, requires (foo) must be a legitimate requires constraint.



A requires expression (that thing that tests whether certain things follow certain constraints) is a distinct construct; it's just introduced by the same keyword. requires (foo f) would be the beginning of a valid requires expression.



What you want is that if you use requires in a place that accepts constraints, you should be able to make a "constraint+expression" out of the requires clause.



So here's the question: if you put requires (foo) into a place that is appropriate for a requires constraint... how far does the parser have to go before it can realize that this is a requires constraint rather than a constraint+expression the way you want it to be?



Consider this:



void bar() requires (foo)
{
//stuff
}


If foo is a type, then (foo) is a parameter list of a requires expression, and everything in the {} is not the body of the function but the body of that requires expression. Otherwise, foo is an expression in a requires clause.



Well, you could say that the compiler should just figure out what foo is first. But C++ really doesn't like it when the basic act of parsing a sequence of tokens requires that the compiler figure out what those identifiers mean before it can make sense of the tokens. Yes, C++ is context-sensitive, so this does happen. But the committee prefers to avoid it where possible.



So yes, it's grammar.






share|improve this answer





















  • 2





    Does it make sense to have a parameter list with a type but without a name?

    – NathanOliver
    Jan 15 at 15:13






  • 3





    @Quentin: There are certainly cases of context-dependency in the C++ grammar. But the committee really does try to minimize that, and they definitely don't like adding more.

    – Nicol Bolas
    Jan 15 at 15:25






  • 3





    @RobertAndrzejuk: If requires appears after a <> set of template arguments or after a function parameter list, then it's a requires-clause. If requires appears where an expression is valid, then it is a requires-expression. This can be determined by the structure of the parse tree, not the contents of the parse tree (the specifics of how an identifier gets defined would be the contents of the tree).

    – Nicol Bolas
    Jan 15 at 17:42






  • 6





    @RobertAndrzejuk: Sure, the requires-expression could have used a different keyword. But keywords have huge costs in C++, as they have the potential to break any program that used the identifier that has become a keyword. The concepts proposal already introduced two keywords: concept and requires. Introducing a third, when the second would be able to cover both cases with no grammatical issues and few user-facing problems, is just wasteful. After all, the only visual problem is that the keyword happens to be repeated twice.

    – Nicol Bolas
    Jan 15 at 19:36






  • 3





    @RobertAndrzejuk it's bad practice anyway to inline constraints like that since you don't get subsumption as if you had written a concept. So taking an identifier for such a low use not recommended feature isn't a good idea.

    – Rakete1111
    Jan 15 at 20:08



















56














The situation is exactly analogous to noexcept(noexcept(...)). Sure, this sounds more like a bad thing than a good thing, but let me explain. :) We'll start with what you already know:



C++11 has "noexcept-clauses" and "noexcept-expressions." They do different things.




  • A noexcept-clause says, "This function should be noexcept when... (some condition)." It goes on a function declaration, takes a boolean parameter, and causes a behavioral change in the declared function.


  • A noexcept-expression says, "Compiler, please tell me whether (some expression) is noexcept." It is itself a boolean expression. It has no "side effects" on the behavior of the program — it's just asking the compiler for the answer to a yes/no question. "Is this expression noexcept?"



We can nest a noexcept-expression inside a noexcept-clause, but we typically consider it bad style to do so.



template<class T>
void incr(T t) noexcept(noexcept(++t)); // NOT SO HOT


It's considered better style to encapsulate the noexcept-expression in a type-trait.



template<class T> inline constexpr bool is_nothrow_incrable_v =
noexcept(++std::declval<T&>()); // BETTER, PART 1

template<class T>
void incr(T t) noexcept(is_nothrow_incrable_v<T>); // BETTER, PART 2




The C++2a Working Draft has "requires-clauses" and "requires-expressions." They do different things.




  • A requires-clause says, "This function should participate in overload resolution when... (some condition)." It goes on a function declaration, takes a boolean parameter, and causes a behavioral change in the declared function.


  • A requires-expression says, "Compiler, please tell me whether (some set of expressions) is well-formed." It is itself a boolean expression. It has no "side effects" on the behavior of the program — it's just asking the compiler for the answer to a yes/no question. "Is this expression well-formed?"



We can nest a requires-expression inside a requires-clause, but we typically consider it bad style to do so.



template<class T>
void incr(T t) requires (requires(T t) { ++t; }); // NOT SO HOT


It's considered better style to encapsulate the requires-expression in a type-trait...



template<class T> inline constexpr bool is_incrable_v =
requires(T t) { ++t; }; // BETTER, PART 1

template<class T>
void incr(T t) requires is_incrable_v<T>; // BETTER, PART 2


...or in a (C++2a Working Draft) concept.



template<class T> concept Incrable =
requires(T t) { ++t; }; // BETTER, PART 1

template<class T>
void incr(T t) requires Incrable<T>; // BETTER, PART 2





share|improve this answer





















  • 1





    I don't really buy this argument. noexcept has the problem that noexcept(f()) could mean either interpret f() as a boolean that we're using to set the specification or check whether or not f() is noexcept. requires doesn't have this ambiguity because the expressions its checking for validity already have to be introduced with {}s. After that, the argument is basically "the grammar says so."

    – Barry
    Jan 16 at 3:29













  • @Barry: See this comment. It appears the {} are optional.

    – Eric
    Jan 16 at 6:48








  • 1





    @Eric The {} are not optional, that's not what that comment shows. However, that is a great comment demonstrating parsing ambiguity. Would probably accept that comment (with some explanation) as a standalone answer

    – Barry
    Jan 16 at 13:06








  • 1





    requires is_nothrow_incrable_v<T>; should be requires is_incrable_v<T>;

    – Ruslan
    Jan 16 at 14:32











  • @Ruslan thanks! fixed.

    – Quuxplusone
    Jan 16 at 16:08



















13














I think cppreference's concepts page explains this. I can explain with "math" so to say, why this must be like this:



If you want to define a concept, you do this:



template<typename T>
concept Addable = requires (T x) { x + x; }; // requires-expression


If you want to declare a function that uses that concept, you do this:



template<typename T> requires Addable<T> // requires-clause, not requires-expression
T add(T a, T b) { return a + b; }


Now if you don't want to define the concept separately, I guess all you have to do is some substitution. Take this part requires (T x) { x + x; }; and replace the Addable<T> part, and you'll get:



template<typename T> requires requires (T x) { x + x; }
T add(T a, T b) { return a + b; }


which is what you're asking about.






share|improve this answer



















  • 4





    I don't think is what the question is asking for. This is explaining the grammar, more or less.

    – Passer By
    Jan 15 at 14:50













  • But why can't you have template<typename T> requires (T x) { x + x; } and require that require can be both the clause and the expression?

    – NathanOliver
    Jan 15 at 14:50








  • 2





    @NathanOliver: Because you're forcing the compiler to interpret one construct as another. A requires-as-constraint clause does not have to be a requires-expression. That's merely one possible use of it.

    – Nicol Bolas
    Jan 15 at 14:51






  • 2





    @TheQuantumPhysicist What I was getting at with my comment is this answer just explains the syntax. Not what actual technical reason we have to requires requires. They could have added something to the grammar to allow template<typename T> requires (T x) { x + x; } but they didn't. Barry wants to know why they didn't

    – NathanOliver
    Jan 15 at 14:58








  • 3





    If we're really playing find-the-grammar-ambiguity here, OK, I'll bite. godbolt.org/z/i6n8kM template<class T> void f(T) requires requires(T (x)) { (void)x; }; means something different if you remove one of the requireses.

    – Quuxplusone
    Jan 15 at 22:43



















9














I found a comment from Andrew Sutton (one of the Concepts authors, who implemented it in gcc) to be quite helpful in this regard, so I thought I'd just quote it here in its near-entirety:




Not so long ago requires-expressions (the phrase introduced by the second requires) was not allowed in constraint-expressions (the phrase introduced by the first requires). It could only appear in concept definitions. In fact, this is exactly what is proposed in the section of that paper where that claim appears.



However, in 2016, there was a proposal to relax that restriction [Editor's note: P0266]. Note the strikethrough of paragraph 4 in section 4 of the paper. And thus was born requires requires.



To tell the truth, I had never actually implemented that restriction in GCC, so it had always been possible. I think that Walter may have discovered that and found it useful, leading to that paper.



Lest anybody think that I wasn't sensitive to writing requires twice, I did spend some time trying to determine if that could be simplified. Short answer: no.



The problem is that there are two grammatical constructs that need to introduced after a template parameter list: very commonly a constraint expression (like P && Q) and occasionally syntactic requirements (like requires (T a) { ... }). That's called a requires-expression.



The first requires introduces the constraint. The second requires introduces the requires-expression. That's just the way the grammar composes. I don't find it confusing at all.



I tried, at one point, to collapse these to a single requires. Unfortunately, that leads to some seriously difficult parsing problems. You can't easily tell, for example if a ( after the requires denotes a nested subexpression or a parameter-list. I don't believe that there is a perfect disambiguation of those syntaxes (see the rationale for uniform initialization syntax; this problem is there too).



So you make a choice: make requires introduce an expression (as it does now) or make it introduce a parameterized list of requirements.



I chose the current approach because most of the time (as in nearly 100% of the time), I want something other than a requires-expression. And in the exceedingly rare case I did want a requires-expression for ad hoc constraints, I really don't mind writing the word twice. It's a an obvious indicator that I haven't developed a sufficiently sound abstraction for the template. (Because if I had, it would have a name.)



I could have chosen to make the requires introduce a requires-expression. That's actually worse, because practically all of your constraints would start to look like this:



template<typename T>
requires { requires Eq<T>; }
void f(T a, T b);


Here, the 2nd requires is called a nested-requirement; it evaluates its expression (other code in the block of the requires-expression is not evaluated). I think this is way worse than the status quo. Now, you get to write requires twice everywhere.



I could also have used more keywords. This is a problem in its own right---and it's not just bike shedding. There might be a way to "redistribute" keywords to avoid the duplication, but I haven't given that serious thought. But that doesn't really change the essence of the problem.







share|improve this answer

































    -9














    Because you are saying that a thing A has a requirement B, and the requirement B has a requirement C.



    The thing A requires B which in turn requires C.



    The "requires" clause itself requires something.



    You have thing A (requiring B (requiring C)).



    Meh. :)






    share|improve this answer



















    • 3





      But according to the other answers, the first and second requires are not conceptually the same thing (one is a clause, one an expression). In fact, if I understand correctly, the two sets of () in requires (requires (T x) { x + x; }) have very different meanings (the outer being optional and always containing a boolean constexpr; the inner being a mandatory part of introducing a requires expression and not allowing actual expressions).

      – Max Langhof
      Jan 15 at 15:28








    • 2





      @MaxLanghof Are you saying that the requirements differ? :D

      – Lightness Races in Orbit
      Jan 15 at 15:42











    Your Answer






    StackExchange.ifUsing("editor", function () {
    StackExchange.using("externalEditor", function () {
    StackExchange.using("snippets", function () {
    StackExchange.snippets.init();
    });
    });
    }, "code-snippets");

    StackExchange.ready(function() {
    var channelOptions = {
    tags: "".split(" "),
    id: "1"
    };
    initTagRenderer("".split(" "), "".split(" "), channelOptions);

    StackExchange.using("externalEditor", function() {
    // Have to fire editor after snippets, if snippets enabled
    if (StackExchange.settings.snippets.snippetsEnabled) {
    StackExchange.using("snippets", function() {
    createEditor();
    });
    }
    else {
    createEditor();
    }
    });

    function createEditor() {
    StackExchange.prepareEditor({
    heartbeatType: 'answer',
    autoActivateHeartbeat: false,
    convertImagesToLinks: true,
    noModals: true,
    showLowRepImageUploadWarning: true,
    reputationToPostImages: 10,
    bindNavPrevention: true,
    postfix: "",
    imageUploader: {
    brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
    contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
    allowUrls: true
    },
    onDemand: true,
    discardSelector: ".discard-answer"
    ,immediatelyShowMarkdownHelp:true
    });


    }
    });














    draft saved

    draft discarded


















    StackExchange.ready(
    function () {
    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f54200988%2fwhy-do-we-require-requires-requires%23new-answer', 'question_page');
    }
    );

    Post as a guest















    Required, but never shown

























    5 Answers
    5






    active

    oldest

    votes








    5 Answers
    5






    active

    oldest

    votes









    active

    oldest

    votes






    active

    oldest

    votes









    72














    It is because the grammar requires it. It does.



    A requires constraint does not have to use a requires expression. It can use any more-or-less arbitrary boolean constant expression. Therefore, requires (foo) must be a legitimate requires constraint.



    A requires expression (that thing that tests whether certain things follow certain constraints) is a distinct construct; it's just introduced by the same keyword. requires (foo f) would be the beginning of a valid requires expression.



    What you want is that if you use requires in a place that accepts constraints, you should be able to make a "constraint+expression" out of the requires clause.



    So here's the question: if you put requires (foo) into a place that is appropriate for a requires constraint... how far does the parser have to go before it can realize that this is a requires constraint rather than a constraint+expression the way you want it to be?



    Consider this:



    void bar() requires (foo)
    {
    //stuff
    }


    If foo is a type, then (foo) is a parameter list of a requires expression, and everything in the {} is not the body of the function but the body of that requires expression. Otherwise, foo is an expression in a requires clause.



    Well, you could say that the compiler should just figure out what foo is first. But C++ really doesn't like it when the basic act of parsing a sequence of tokens requires that the compiler figure out what those identifiers mean before it can make sense of the tokens. Yes, C++ is context-sensitive, so this does happen. But the committee prefers to avoid it where possible.



    So yes, it's grammar.






    share|improve this answer





















    • 2





      Does it make sense to have a parameter list with a type but without a name?

      – NathanOliver
      Jan 15 at 15:13






    • 3





      @Quentin: There are certainly cases of context-dependency in the C++ grammar. But the committee really does try to minimize that, and they definitely don't like adding more.

      – Nicol Bolas
      Jan 15 at 15:25






    • 3





      @RobertAndrzejuk: If requires appears after a <> set of template arguments or after a function parameter list, then it's a requires-clause. If requires appears where an expression is valid, then it is a requires-expression. This can be determined by the structure of the parse tree, not the contents of the parse tree (the specifics of how an identifier gets defined would be the contents of the tree).

      – Nicol Bolas
      Jan 15 at 17:42






    • 6





      @RobertAndrzejuk: Sure, the requires-expression could have used a different keyword. But keywords have huge costs in C++, as they have the potential to break any program that used the identifier that has become a keyword. The concepts proposal already introduced two keywords: concept and requires. Introducing a third, when the second would be able to cover both cases with no grammatical issues and few user-facing problems, is just wasteful. After all, the only visual problem is that the keyword happens to be repeated twice.

      – Nicol Bolas
      Jan 15 at 19:36






    • 3





      @RobertAndrzejuk it's bad practice anyway to inline constraints like that since you don't get subsumption as if you had written a concept. So taking an identifier for such a low use not recommended feature isn't a good idea.

      – Rakete1111
      Jan 15 at 20:08
















    72














    It is because the grammar requires it. It does.



    A requires constraint does not have to use a requires expression. It can use any more-or-less arbitrary boolean constant expression. Therefore, requires (foo) must be a legitimate requires constraint.



    A requires expression (that thing that tests whether certain things follow certain constraints) is a distinct construct; it's just introduced by the same keyword. requires (foo f) would be the beginning of a valid requires expression.



    What you want is that if you use requires in a place that accepts constraints, you should be able to make a "constraint+expression" out of the requires clause.



    So here's the question: if you put requires (foo) into a place that is appropriate for a requires constraint... how far does the parser have to go before it can realize that this is a requires constraint rather than a constraint+expression the way you want it to be?



    Consider this:



    void bar() requires (foo)
    {
    //stuff
    }


    If foo is a type, then (foo) is a parameter list of a requires expression, and everything in the {} is not the body of the function but the body of that requires expression. Otherwise, foo is an expression in a requires clause.



    Well, you could say that the compiler should just figure out what foo is first. But C++ really doesn't like it when the basic act of parsing a sequence of tokens requires that the compiler figure out what those identifiers mean before it can make sense of the tokens. Yes, C++ is context-sensitive, so this does happen. But the committee prefers to avoid it where possible.



    So yes, it's grammar.






    share|improve this answer





















    • 2





      Does it make sense to have a parameter list with a type but without a name?

      – NathanOliver
      Jan 15 at 15:13






    • 3





      @Quentin: There are certainly cases of context-dependency in the C++ grammar. But the committee really does try to minimize that, and they definitely don't like adding more.

      – Nicol Bolas
      Jan 15 at 15:25






    • 3





      @RobertAndrzejuk: If requires appears after a <> set of template arguments or after a function parameter list, then it's a requires-clause. If requires appears where an expression is valid, then it is a requires-expression. This can be determined by the structure of the parse tree, not the contents of the parse tree (the specifics of how an identifier gets defined would be the contents of the tree).

      – Nicol Bolas
      Jan 15 at 17:42






    • 6





      @RobertAndrzejuk: Sure, the requires-expression could have used a different keyword. But keywords have huge costs in C++, as they have the potential to break any program that used the identifier that has become a keyword. The concepts proposal already introduced two keywords: concept and requires. Introducing a third, when the second would be able to cover both cases with no grammatical issues and few user-facing problems, is just wasteful. After all, the only visual problem is that the keyword happens to be repeated twice.

      – Nicol Bolas
      Jan 15 at 19:36






    • 3





      @RobertAndrzejuk it's bad practice anyway to inline constraints like that since you don't get subsumption as if you had written a concept. So taking an identifier for such a low use not recommended feature isn't a good idea.

      – Rakete1111
      Jan 15 at 20:08














    72












    72








    72







    It is because the grammar requires it. It does.



    A requires constraint does not have to use a requires expression. It can use any more-or-less arbitrary boolean constant expression. Therefore, requires (foo) must be a legitimate requires constraint.



    A requires expression (that thing that tests whether certain things follow certain constraints) is a distinct construct; it's just introduced by the same keyword. requires (foo f) would be the beginning of a valid requires expression.



    What you want is that if you use requires in a place that accepts constraints, you should be able to make a "constraint+expression" out of the requires clause.



    So here's the question: if you put requires (foo) into a place that is appropriate for a requires constraint... how far does the parser have to go before it can realize that this is a requires constraint rather than a constraint+expression the way you want it to be?



    Consider this:



    void bar() requires (foo)
    {
    //stuff
    }


    If foo is a type, then (foo) is a parameter list of a requires expression, and everything in the {} is not the body of the function but the body of that requires expression. Otherwise, foo is an expression in a requires clause.



    Well, you could say that the compiler should just figure out what foo is first. But C++ really doesn't like it when the basic act of parsing a sequence of tokens requires that the compiler figure out what those identifiers mean before it can make sense of the tokens. Yes, C++ is context-sensitive, so this does happen. But the committee prefers to avoid it where possible.



    So yes, it's grammar.






    share|improve this answer















    It is because the grammar requires it. It does.



    A requires constraint does not have to use a requires expression. It can use any more-or-less arbitrary boolean constant expression. Therefore, requires (foo) must be a legitimate requires constraint.



    A requires expression (that thing that tests whether certain things follow certain constraints) is a distinct construct; it's just introduced by the same keyword. requires (foo f) would be the beginning of a valid requires expression.



    What you want is that if you use requires in a place that accepts constraints, you should be able to make a "constraint+expression" out of the requires clause.



    So here's the question: if you put requires (foo) into a place that is appropriate for a requires constraint... how far does the parser have to go before it can realize that this is a requires constraint rather than a constraint+expression the way you want it to be?



    Consider this:



    void bar() requires (foo)
    {
    //stuff
    }


    If foo is a type, then (foo) is a parameter list of a requires expression, and everything in the {} is not the body of the function but the body of that requires expression. Otherwise, foo is an expression in a requires clause.



    Well, you could say that the compiler should just figure out what foo is first. But C++ really doesn't like it when the basic act of parsing a sequence of tokens requires that the compiler figure out what those identifiers mean before it can make sense of the tokens. Yes, C++ is context-sensitive, so this does happen. But the committee prefers to avoid it where possible.



    So yes, it's grammar.







    share|improve this answer














    share|improve this answer



    share|improve this answer








    edited Jan 15 at 17:01

























    answered Jan 15 at 15:03









    Nicol BolasNicol Bolas

    286k33474648




    286k33474648








    • 2





      Does it make sense to have a parameter list with a type but without a name?

      – NathanOliver
      Jan 15 at 15:13






    • 3





      @Quentin: There are certainly cases of context-dependency in the C++ grammar. But the committee really does try to minimize that, and they definitely don't like adding more.

      – Nicol Bolas
      Jan 15 at 15:25






    • 3





      @RobertAndrzejuk: If requires appears after a <> set of template arguments or after a function parameter list, then it's a requires-clause. If requires appears where an expression is valid, then it is a requires-expression. This can be determined by the structure of the parse tree, not the contents of the parse tree (the specifics of how an identifier gets defined would be the contents of the tree).

      – Nicol Bolas
      Jan 15 at 17:42






    • 6





      @RobertAndrzejuk: Sure, the requires-expression could have used a different keyword. But keywords have huge costs in C++, as they have the potential to break any program that used the identifier that has become a keyword. The concepts proposal already introduced two keywords: concept and requires. Introducing a third, when the second would be able to cover both cases with no grammatical issues and few user-facing problems, is just wasteful. After all, the only visual problem is that the keyword happens to be repeated twice.

      – Nicol Bolas
      Jan 15 at 19:36






    • 3





      @RobertAndrzejuk it's bad practice anyway to inline constraints like that since you don't get subsumption as if you had written a concept. So taking an identifier for such a low use not recommended feature isn't a good idea.

      – Rakete1111
      Jan 15 at 20:08














    • 2





      Does it make sense to have a parameter list with a type but without a name?

      – NathanOliver
      Jan 15 at 15:13






    • 3





      @Quentin: There are certainly cases of context-dependency in the C++ grammar. But the committee really does try to minimize that, and they definitely don't like adding more.

      – Nicol Bolas
      Jan 15 at 15:25






    • 3





      @RobertAndrzejuk: If requires appears after a <> set of template arguments or after a function parameter list, then it's a requires-clause. If requires appears where an expression is valid, then it is a requires-expression. This can be determined by the structure of the parse tree, not the contents of the parse tree (the specifics of how an identifier gets defined would be the contents of the tree).

      – Nicol Bolas
      Jan 15 at 17:42






    • 6





      @RobertAndrzejuk: Sure, the requires-expression could have used a different keyword. But keywords have huge costs in C++, as they have the potential to break any program that used the identifier that has become a keyword. The concepts proposal already introduced two keywords: concept and requires. Introducing a third, when the second would be able to cover both cases with no grammatical issues and few user-facing problems, is just wasteful. After all, the only visual problem is that the keyword happens to be repeated twice.

      – Nicol Bolas
      Jan 15 at 19:36






    • 3





      @RobertAndrzejuk it's bad practice anyway to inline constraints like that since you don't get subsumption as if you had written a concept. So taking an identifier for such a low use not recommended feature isn't a good idea.

      – Rakete1111
      Jan 15 at 20:08








    2




    2





    Does it make sense to have a parameter list with a type but without a name?

    – NathanOliver
    Jan 15 at 15:13





    Does it make sense to have a parameter list with a type but without a name?

    – NathanOliver
    Jan 15 at 15:13




    3




    3





    @Quentin: There are certainly cases of context-dependency in the C++ grammar. But the committee really does try to minimize that, and they definitely don't like adding more.

    – Nicol Bolas
    Jan 15 at 15:25





    @Quentin: There are certainly cases of context-dependency in the C++ grammar. But the committee really does try to minimize that, and they definitely don't like adding more.

    – Nicol Bolas
    Jan 15 at 15:25




    3




    3





    @RobertAndrzejuk: If requires appears after a <> set of template arguments or after a function parameter list, then it's a requires-clause. If requires appears where an expression is valid, then it is a requires-expression. This can be determined by the structure of the parse tree, not the contents of the parse tree (the specifics of how an identifier gets defined would be the contents of the tree).

    – Nicol Bolas
    Jan 15 at 17:42





    @RobertAndrzejuk: If requires appears after a <> set of template arguments or after a function parameter list, then it's a requires-clause. If requires appears where an expression is valid, then it is a requires-expression. This can be determined by the structure of the parse tree, not the contents of the parse tree (the specifics of how an identifier gets defined would be the contents of the tree).

    – Nicol Bolas
    Jan 15 at 17:42




    6




    6





    @RobertAndrzejuk: Sure, the requires-expression could have used a different keyword. But keywords have huge costs in C++, as they have the potential to break any program that used the identifier that has become a keyword. The concepts proposal already introduced two keywords: concept and requires. Introducing a third, when the second would be able to cover both cases with no grammatical issues and few user-facing problems, is just wasteful. After all, the only visual problem is that the keyword happens to be repeated twice.

    – Nicol Bolas
    Jan 15 at 19:36





    @RobertAndrzejuk: Sure, the requires-expression could have used a different keyword. But keywords have huge costs in C++, as they have the potential to break any program that used the identifier that has become a keyword. The concepts proposal already introduced two keywords: concept and requires. Introducing a third, when the second would be able to cover both cases with no grammatical issues and few user-facing problems, is just wasteful. After all, the only visual problem is that the keyword happens to be repeated twice.

    – Nicol Bolas
    Jan 15 at 19:36




    3




    3





    @RobertAndrzejuk it's bad practice anyway to inline constraints like that since you don't get subsumption as if you had written a concept. So taking an identifier for such a low use not recommended feature isn't a good idea.

    – Rakete1111
    Jan 15 at 20:08





    @RobertAndrzejuk it's bad practice anyway to inline constraints like that since you don't get subsumption as if you had written a concept. So taking an identifier for such a low use not recommended feature isn't a good idea.

    – Rakete1111
    Jan 15 at 20:08













    56














    The situation is exactly analogous to noexcept(noexcept(...)). Sure, this sounds more like a bad thing than a good thing, but let me explain. :) We'll start with what you already know:



    C++11 has "noexcept-clauses" and "noexcept-expressions." They do different things.




    • A noexcept-clause says, "This function should be noexcept when... (some condition)." It goes on a function declaration, takes a boolean parameter, and causes a behavioral change in the declared function.


    • A noexcept-expression says, "Compiler, please tell me whether (some expression) is noexcept." It is itself a boolean expression. It has no "side effects" on the behavior of the program — it's just asking the compiler for the answer to a yes/no question. "Is this expression noexcept?"



    We can nest a noexcept-expression inside a noexcept-clause, but we typically consider it bad style to do so.



    template<class T>
    void incr(T t) noexcept(noexcept(++t)); // NOT SO HOT


    It's considered better style to encapsulate the noexcept-expression in a type-trait.



    template<class T> inline constexpr bool is_nothrow_incrable_v =
    noexcept(++std::declval<T&>()); // BETTER, PART 1

    template<class T>
    void incr(T t) noexcept(is_nothrow_incrable_v<T>); // BETTER, PART 2




    The C++2a Working Draft has "requires-clauses" and "requires-expressions." They do different things.




    • A requires-clause says, "This function should participate in overload resolution when... (some condition)." It goes on a function declaration, takes a boolean parameter, and causes a behavioral change in the declared function.


    • A requires-expression says, "Compiler, please tell me whether (some set of expressions) is well-formed." It is itself a boolean expression. It has no "side effects" on the behavior of the program — it's just asking the compiler for the answer to a yes/no question. "Is this expression well-formed?"



    We can nest a requires-expression inside a requires-clause, but we typically consider it bad style to do so.



    template<class T>
    void incr(T t) requires (requires(T t) { ++t; }); // NOT SO HOT


    It's considered better style to encapsulate the requires-expression in a type-trait...



    template<class T> inline constexpr bool is_incrable_v =
    requires(T t) { ++t; }; // BETTER, PART 1

    template<class T>
    void incr(T t) requires is_incrable_v<T>; // BETTER, PART 2


    ...or in a (C++2a Working Draft) concept.



    template<class T> concept Incrable =
    requires(T t) { ++t; }; // BETTER, PART 1

    template<class T>
    void incr(T t) requires Incrable<T>; // BETTER, PART 2





    share|improve this answer





















    • 1





      I don't really buy this argument. noexcept has the problem that noexcept(f()) could mean either interpret f() as a boolean that we're using to set the specification or check whether or not f() is noexcept. requires doesn't have this ambiguity because the expressions its checking for validity already have to be introduced with {}s. After that, the argument is basically "the grammar says so."

      – Barry
      Jan 16 at 3:29













    • @Barry: See this comment. It appears the {} are optional.

      – Eric
      Jan 16 at 6:48








    • 1





      @Eric The {} are not optional, that's not what that comment shows. However, that is a great comment demonstrating parsing ambiguity. Would probably accept that comment (with some explanation) as a standalone answer

      – Barry
      Jan 16 at 13:06








    • 1





      requires is_nothrow_incrable_v<T>; should be requires is_incrable_v<T>;

      – Ruslan
      Jan 16 at 14:32











    • @Ruslan thanks! fixed.

      – Quuxplusone
      Jan 16 at 16:08
















    56














    The situation is exactly analogous to noexcept(noexcept(...)). Sure, this sounds more like a bad thing than a good thing, but let me explain. :) We'll start with what you already know:



    C++11 has "noexcept-clauses" and "noexcept-expressions." They do different things.




    • A noexcept-clause says, "This function should be noexcept when... (some condition)." It goes on a function declaration, takes a boolean parameter, and causes a behavioral change in the declared function.


    • A noexcept-expression says, "Compiler, please tell me whether (some expression) is noexcept." It is itself a boolean expression. It has no "side effects" on the behavior of the program — it's just asking the compiler for the answer to a yes/no question. "Is this expression noexcept?"



    We can nest a noexcept-expression inside a noexcept-clause, but we typically consider it bad style to do so.



    template<class T>
    void incr(T t) noexcept(noexcept(++t)); // NOT SO HOT


    It's considered better style to encapsulate the noexcept-expression in a type-trait.



    template<class T> inline constexpr bool is_nothrow_incrable_v =
    noexcept(++std::declval<T&>()); // BETTER, PART 1

    template<class T>
    void incr(T t) noexcept(is_nothrow_incrable_v<T>); // BETTER, PART 2




    The C++2a Working Draft has "requires-clauses" and "requires-expressions." They do different things.




    • A requires-clause says, "This function should participate in overload resolution when... (some condition)." It goes on a function declaration, takes a boolean parameter, and causes a behavioral change in the declared function.


    • A requires-expression says, "Compiler, please tell me whether (some set of expressions) is well-formed." It is itself a boolean expression. It has no "side effects" on the behavior of the program — it's just asking the compiler for the answer to a yes/no question. "Is this expression well-formed?"



    We can nest a requires-expression inside a requires-clause, but we typically consider it bad style to do so.



    template<class T>
    void incr(T t) requires (requires(T t) { ++t; }); // NOT SO HOT


    It's considered better style to encapsulate the requires-expression in a type-trait...



    template<class T> inline constexpr bool is_incrable_v =
    requires(T t) { ++t; }; // BETTER, PART 1

    template<class T>
    void incr(T t) requires is_incrable_v<T>; // BETTER, PART 2


    ...or in a (C++2a Working Draft) concept.



    template<class T> concept Incrable =
    requires(T t) { ++t; }; // BETTER, PART 1

    template<class T>
    void incr(T t) requires Incrable<T>; // BETTER, PART 2





    share|improve this answer





















    • 1





      I don't really buy this argument. noexcept has the problem that noexcept(f()) could mean either interpret f() as a boolean that we're using to set the specification or check whether or not f() is noexcept. requires doesn't have this ambiguity because the expressions its checking for validity already have to be introduced with {}s. After that, the argument is basically "the grammar says so."

      – Barry
      Jan 16 at 3:29













    • @Barry: See this comment. It appears the {} are optional.

      – Eric
      Jan 16 at 6:48








    • 1





      @Eric The {} are not optional, that's not what that comment shows. However, that is a great comment demonstrating parsing ambiguity. Would probably accept that comment (with some explanation) as a standalone answer

      – Barry
      Jan 16 at 13:06








    • 1





      requires is_nothrow_incrable_v<T>; should be requires is_incrable_v<T>;

      – Ruslan
      Jan 16 at 14:32











    • @Ruslan thanks! fixed.

      – Quuxplusone
      Jan 16 at 16:08














    56












    56








    56







    The situation is exactly analogous to noexcept(noexcept(...)). Sure, this sounds more like a bad thing than a good thing, but let me explain. :) We'll start with what you already know:



    C++11 has "noexcept-clauses" and "noexcept-expressions." They do different things.




    • A noexcept-clause says, "This function should be noexcept when... (some condition)." It goes on a function declaration, takes a boolean parameter, and causes a behavioral change in the declared function.


    • A noexcept-expression says, "Compiler, please tell me whether (some expression) is noexcept." It is itself a boolean expression. It has no "side effects" on the behavior of the program — it's just asking the compiler for the answer to a yes/no question. "Is this expression noexcept?"



    We can nest a noexcept-expression inside a noexcept-clause, but we typically consider it bad style to do so.



    template<class T>
    void incr(T t) noexcept(noexcept(++t)); // NOT SO HOT


    It's considered better style to encapsulate the noexcept-expression in a type-trait.



    template<class T> inline constexpr bool is_nothrow_incrable_v =
    noexcept(++std::declval<T&>()); // BETTER, PART 1

    template<class T>
    void incr(T t) noexcept(is_nothrow_incrable_v<T>); // BETTER, PART 2




    The C++2a Working Draft has "requires-clauses" and "requires-expressions." They do different things.




    • A requires-clause says, "This function should participate in overload resolution when... (some condition)." It goes on a function declaration, takes a boolean parameter, and causes a behavioral change in the declared function.


    • A requires-expression says, "Compiler, please tell me whether (some set of expressions) is well-formed." It is itself a boolean expression. It has no "side effects" on the behavior of the program — it's just asking the compiler for the answer to a yes/no question. "Is this expression well-formed?"



    We can nest a requires-expression inside a requires-clause, but we typically consider it bad style to do so.



    template<class T>
    void incr(T t) requires (requires(T t) { ++t; }); // NOT SO HOT


    It's considered better style to encapsulate the requires-expression in a type-trait...



    template<class T> inline constexpr bool is_incrable_v =
    requires(T t) { ++t; }; // BETTER, PART 1

    template<class T>
    void incr(T t) requires is_incrable_v<T>; // BETTER, PART 2


    ...or in a (C++2a Working Draft) concept.



    template<class T> concept Incrable =
    requires(T t) { ++t; }; // BETTER, PART 1

    template<class T>
    void incr(T t) requires Incrable<T>; // BETTER, PART 2





    share|improve this answer















    The situation is exactly analogous to noexcept(noexcept(...)). Sure, this sounds more like a bad thing than a good thing, but let me explain. :) We'll start with what you already know:



    C++11 has "noexcept-clauses" and "noexcept-expressions." They do different things.




    • A noexcept-clause says, "This function should be noexcept when... (some condition)." It goes on a function declaration, takes a boolean parameter, and causes a behavioral change in the declared function.


    • A noexcept-expression says, "Compiler, please tell me whether (some expression) is noexcept." It is itself a boolean expression. It has no "side effects" on the behavior of the program — it's just asking the compiler for the answer to a yes/no question. "Is this expression noexcept?"



    We can nest a noexcept-expression inside a noexcept-clause, but we typically consider it bad style to do so.



    template<class T>
    void incr(T t) noexcept(noexcept(++t)); // NOT SO HOT


    It's considered better style to encapsulate the noexcept-expression in a type-trait.



    template<class T> inline constexpr bool is_nothrow_incrable_v =
    noexcept(++std::declval<T&>()); // BETTER, PART 1

    template<class T>
    void incr(T t) noexcept(is_nothrow_incrable_v<T>); // BETTER, PART 2




    The C++2a Working Draft has "requires-clauses" and "requires-expressions." They do different things.




    • A requires-clause says, "This function should participate in overload resolution when... (some condition)." It goes on a function declaration, takes a boolean parameter, and causes a behavioral change in the declared function.


    • A requires-expression says, "Compiler, please tell me whether (some set of expressions) is well-formed." It is itself a boolean expression. It has no "side effects" on the behavior of the program — it's just asking the compiler for the answer to a yes/no question. "Is this expression well-formed?"



    We can nest a requires-expression inside a requires-clause, but we typically consider it bad style to do so.



    template<class T>
    void incr(T t) requires (requires(T t) { ++t; }); // NOT SO HOT


    It's considered better style to encapsulate the requires-expression in a type-trait...



    template<class T> inline constexpr bool is_incrable_v =
    requires(T t) { ++t; }; // BETTER, PART 1

    template<class T>
    void incr(T t) requires is_incrable_v<T>; // BETTER, PART 2


    ...or in a (C++2a Working Draft) concept.



    template<class T> concept Incrable =
    requires(T t) { ++t; }; // BETTER, PART 1

    template<class T>
    void incr(T t) requires Incrable<T>; // BETTER, PART 2






    share|improve this answer














    share|improve this answer



    share|improve this answer








    edited Jan 16 at 16:08

























    answered Jan 15 at 16:36









    QuuxplusoneQuuxplusone

    12.2k34495




    12.2k34495








    • 1





      I don't really buy this argument. noexcept has the problem that noexcept(f()) could mean either interpret f() as a boolean that we're using to set the specification or check whether or not f() is noexcept. requires doesn't have this ambiguity because the expressions its checking for validity already have to be introduced with {}s. After that, the argument is basically "the grammar says so."

      – Barry
      Jan 16 at 3:29













    • @Barry: See this comment. It appears the {} are optional.

      – Eric
      Jan 16 at 6:48








    • 1





      @Eric The {} are not optional, that's not what that comment shows. However, that is a great comment demonstrating parsing ambiguity. Would probably accept that comment (with some explanation) as a standalone answer

      – Barry
      Jan 16 at 13:06








    • 1





      requires is_nothrow_incrable_v<T>; should be requires is_incrable_v<T>;

      – Ruslan
      Jan 16 at 14:32











    • @Ruslan thanks! fixed.

      – Quuxplusone
      Jan 16 at 16:08














    • 1





      I don't really buy this argument. noexcept has the problem that noexcept(f()) could mean either interpret f() as a boolean that we're using to set the specification or check whether or not f() is noexcept. requires doesn't have this ambiguity because the expressions its checking for validity already have to be introduced with {}s. After that, the argument is basically "the grammar says so."

      – Barry
      Jan 16 at 3:29













    • @Barry: See this comment. It appears the {} are optional.

      – Eric
      Jan 16 at 6:48








    • 1





      @Eric The {} are not optional, that's not what that comment shows. However, that is a great comment demonstrating parsing ambiguity. Would probably accept that comment (with some explanation) as a standalone answer

      – Barry
      Jan 16 at 13:06








    • 1





      requires is_nothrow_incrable_v<T>; should be requires is_incrable_v<T>;

      – Ruslan
      Jan 16 at 14:32











    • @Ruslan thanks! fixed.

      – Quuxplusone
      Jan 16 at 16:08








    1




    1





    I don't really buy this argument. noexcept has the problem that noexcept(f()) could mean either interpret f() as a boolean that we're using to set the specification or check whether or not f() is noexcept. requires doesn't have this ambiguity because the expressions its checking for validity already have to be introduced with {}s. After that, the argument is basically "the grammar says so."

    – Barry
    Jan 16 at 3:29







    I don't really buy this argument. noexcept has the problem that noexcept(f()) could mean either interpret f() as a boolean that we're using to set the specification or check whether or not f() is noexcept. requires doesn't have this ambiguity because the expressions its checking for validity already have to be introduced with {}s. After that, the argument is basically "the grammar says so."

    – Barry
    Jan 16 at 3:29















    @Barry: See this comment. It appears the {} are optional.

    – Eric
    Jan 16 at 6:48







    @Barry: See this comment. It appears the {} are optional.

    – Eric
    Jan 16 at 6:48






    1




    1





    @Eric The {} are not optional, that's not what that comment shows. However, that is a great comment demonstrating parsing ambiguity. Would probably accept that comment (with some explanation) as a standalone answer

    – Barry
    Jan 16 at 13:06







    @Eric The {} are not optional, that's not what that comment shows. However, that is a great comment demonstrating parsing ambiguity. Would probably accept that comment (with some explanation) as a standalone answer

    – Barry
    Jan 16 at 13:06






    1




    1





    requires is_nothrow_incrable_v<T>; should be requires is_incrable_v<T>;

    – Ruslan
    Jan 16 at 14:32





    requires is_nothrow_incrable_v<T>; should be requires is_incrable_v<T>;

    – Ruslan
    Jan 16 at 14:32













    @Ruslan thanks! fixed.

    – Quuxplusone
    Jan 16 at 16:08





    @Ruslan thanks! fixed.

    – Quuxplusone
    Jan 16 at 16:08











    13














    I think cppreference's concepts page explains this. I can explain with "math" so to say, why this must be like this:



    If you want to define a concept, you do this:



    template<typename T>
    concept Addable = requires (T x) { x + x; }; // requires-expression


    If you want to declare a function that uses that concept, you do this:



    template<typename T> requires Addable<T> // requires-clause, not requires-expression
    T add(T a, T b) { return a + b; }


    Now if you don't want to define the concept separately, I guess all you have to do is some substitution. Take this part requires (T x) { x + x; }; and replace the Addable<T> part, and you'll get:



    template<typename T> requires requires (T x) { x + x; }
    T add(T a, T b) { return a + b; }


    which is what you're asking about.






    share|improve this answer



















    • 4





      I don't think is what the question is asking for. This is explaining the grammar, more or less.

      – Passer By
      Jan 15 at 14:50













    • But why can't you have template<typename T> requires (T x) { x + x; } and require that require can be both the clause and the expression?

      – NathanOliver
      Jan 15 at 14:50








    • 2





      @NathanOliver: Because you're forcing the compiler to interpret one construct as another. A requires-as-constraint clause does not have to be a requires-expression. That's merely one possible use of it.

      – Nicol Bolas
      Jan 15 at 14:51






    • 2





      @TheQuantumPhysicist What I was getting at with my comment is this answer just explains the syntax. Not what actual technical reason we have to requires requires. They could have added something to the grammar to allow template<typename T> requires (T x) { x + x; } but they didn't. Barry wants to know why they didn't

      – NathanOliver
      Jan 15 at 14:58








    • 3





      If we're really playing find-the-grammar-ambiguity here, OK, I'll bite. godbolt.org/z/i6n8kM template<class T> void f(T) requires requires(T (x)) { (void)x; }; means something different if you remove one of the requireses.

      – Quuxplusone
      Jan 15 at 22:43
















    13














    I think cppreference's concepts page explains this. I can explain with "math" so to say, why this must be like this:



    If you want to define a concept, you do this:



    template<typename T>
    concept Addable = requires (T x) { x + x; }; // requires-expression


    If you want to declare a function that uses that concept, you do this:



    template<typename T> requires Addable<T> // requires-clause, not requires-expression
    T add(T a, T b) { return a + b; }


    Now if you don't want to define the concept separately, I guess all you have to do is some substitution. Take this part requires (T x) { x + x; }; and replace the Addable<T> part, and you'll get:



    template<typename T> requires requires (T x) { x + x; }
    T add(T a, T b) { return a + b; }


    which is what you're asking about.






    share|improve this answer



















    • 4





      I don't think is what the question is asking for. This is explaining the grammar, more or less.

      – Passer By
      Jan 15 at 14:50













    • But why can't you have template<typename T> requires (T x) { x + x; } and require that require can be both the clause and the expression?

      – NathanOliver
      Jan 15 at 14:50








    • 2





      @NathanOliver: Because you're forcing the compiler to interpret one construct as another. A requires-as-constraint clause does not have to be a requires-expression. That's merely one possible use of it.

      – Nicol Bolas
      Jan 15 at 14:51






    • 2





      @TheQuantumPhysicist What I was getting at with my comment is this answer just explains the syntax. Not what actual technical reason we have to requires requires. They could have added something to the grammar to allow template<typename T> requires (T x) { x + x; } but they didn't. Barry wants to know why they didn't

      – NathanOliver
      Jan 15 at 14:58








    • 3





      If we're really playing find-the-grammar-ambiguity here, OK, I'll bite. godbolt.org/z/i6n8kM template<class T> void f(T) requires requires(T (x)) { (void)x; }; means something different if you remove one of the requireses.

      – Quuxplusone
      Jan 15 at 22:43














    13












    13








    13







    I think cppreference's concepts page explains this. I can explain with "math" so to say, why this must be like this:



    If you want to define a concept, you do this:



    template<typename T>
    concept Addable = requires (T x) { x + x; }; // requires-expression


    If you want to declare a function that uses that concept, you do this:



    template<typename T> requires Addable<T> // requires-clause, not requires-expression
    T add(T a, T b) { return a + b; }


    Now if you don't want to define the concept separately, I guess all you have to do is some substitution. Take this part requires (T x) { x + x; }; and replace the Addable<T> part, and you'll get:



    template<typename T> requires requires (T x) { x + x; }
    T add(T a, T b) { return a + b; }


    which is what you're asking about.






    share|improve this answer













    I think cppreference's concepts page explains this. I can explain with "math" so to say, why this must be like this:



    If you want to define a concept, you do this:



    template<typename T>
    concept Addable = requires (T x) { x + x; }; // requires-expression


    If you want to declare a function that uses that concept, you do this:



    template<typename T> requires Addable<T> // requires-clause, not requires-expression
    T add(T a, T b) { return a + b; }


    Now if you don't want to define the concept separately, I guess all you have to do is some substitution. Take this part requires (T x) { x + x; }; and replace the Addable<T> part, and you'll get:



    template<typename T> requires requires (T x) { x + x; }
    T add(T a, T b) { return a + b; }


    which is what you're asking about.







    share|improve this answer












    share|improve this answer



    share|improve this answer










    answered Jan 15 at 14:47









    The Quantum PhysicistThe Quantum Physicist

    11.9k64799




    11.9k64799








    • 4





      I don't think is what the question is asking for. This is explaining the grammar, more or less.

      – Passer By
      Jan 15 at 14:50













    • But why can't you have template<typename T> requires (T x) { x + x; } and require that require can be both the clause and the expression?

      – NathanOliver
      Jan 15 at 14:50








    • 2





      @NathanOliver: Because you're forcing the compiler to interpret one construct as another. A requires-as-constraint clause does not have to be a requires-expression. That's merely one possible use of it.

      – Nicol Bolas
      Jan 15 at 14:51






    • 2





      @TheQuantumPhysicist What I was getting at with my comment is this answer just explains the syntax. Not what actual technical reason we have to requires requires. They could have added something to the grammar to allow template<typename T> requires (T x) { x + x; } but they didn't. Barry wants to know why they didn't

      – NathanOliver
      Jan 15 at 14:58








    • 3





      If we're really playing find-the-grammar-ambiguity here, OK, I'll bite. godbolt.org/z/i6n8kM template<class T> void f(T) requires requires(T (x)) { (void)x; }; means something different if you remove one of the requireses.

      – Quuxplusone
      Jan 15 at 22:43














    • 4





      I don't think is what the question is asking for. This is explaining the grammar, more or less.

      – Passer By
      Jan 15 at 14:50













    • But why can't you have template<typename T> requires (T x) { x + x; } and require that require can be both the clause and the expression?

      – NathanOliver
      Jan 15 at 14:50








    • 2





      @NathanOliver: Because you're forcing the compiler to interpret one construct as another. A requires-as-constraint clause does not have to be a requires-expression. That's merely one possible use of it.

      – Nicol Bolas
      Jan 15 at 14:51






    • 2





      @TheQuantumPhysicist What I was getting at with my comment is this answer just explains the syntax. Not what actual technical reason we have to requires requires. They could have added something to the grammar to allow template<typename T> requires (T x) { x + x; } but they didn't. Barry wants to know why they didn't

      – NathanOliver
      Jan 15 at 14:58








    • 3





      If we're really playing find-the-grammar-ambiguity here, OK, I'll bite. godbolt.org/z/i6n8kM template<class T> void f(T) requires requires(T (x)) { (void)x; }; means something different if you remove one of the requireses.

      – Quuxplusone
      Jan 15 at 22:43








    4




    4





    I don't think is what the question is asking for. This is explaining the grammar, more or less.

    – Passer By
    Jan 15 at 14:50







    I don't think is what the question is asking for. This is explaining the grammar, more or less.

    – Passer By
    Jan 15 at 14:50















    But why can't you have template<typename T> requires (T x) { x + x; } and require that require can be both the clause and the expression?

    – NathanOliver
    Jan 15 at 14:50







    But why can't you have template<typename T> requires (T x) { x + x; } and require that require can be both the clause and the expression?

    – NathanOliver
    Jan 15 at 14:50






    2




    2





    @NathanOliver: Because you're forcing the compiler to interpret one construct as another. A requires-as-constraint clause does not have to be a requires-expression. That's merely one possible use of it.

    – Nicol Bolas
    Jan 15 at 14:51





    @NathanOliver: Because you're forcing the compiler to interpret one construct as another. A requires-as-constraint clause does not have to be a requires-expression. That's merely one possible use of it.

    – Nicol Bolas
    Jan 15 at 14:51




    2




    2





    @TheQuantumPhysicist What I was getting at with my comment is this answer just explains the syntax. Not what actual technical reason we have to requires requires. They could have added something to the grammar to allow template<typename T> requires (T x) { x + x; } but they didn't. Barry wants to know why they didn't

    – NathanOliver
    Jan 15 at 14:58







    @TheQuantumPhysicist What I was getting at with my comment is this answer just explains the syntax. Not what actual technical reason we have to requires requires. They could have added something to the grammar to allow template<typename T> requires (T x) { x + x; } but they didn't. Barry wants to know why they didn't

    – NathanOliver
    Jan 15 at 14:58






    3




    3





    If we're really playing find-the-grammar-ambiguity here, OK, I'll bite. godbolt.org/z/i6n8kM template<class T> void f(T) requires requires(T (x)) { (void)x; }; means something different if you remove one of the requireses.

    – Quuxplusone
    Jan 15 at 22:43





    If we're really playing find-the-grammar-ambiguity here, OK, I'll bite. godbolt.org/z/i6n8kM template<class T> void f(T) requires requires(T (x)) { (void)x; }; means something different if you remove one of the requireses.

    – Quuxplusone
    Jan 15 at 22:43











    9














    I found a comment from Andrew Sutton (one of the Concepts authors, who implemented it in gcc) to be quite helpful in this regard, so I thought I'd just quote it here in its near-entirety:




    Not so long ago requires-expressions (the phrase introduced by the second requires) was not allowed in constraint-expressions (the phrase introduced by the first requires). It could only appear in concept definitions. In fact, this is exactly what is proposed in the section of that paper where that claim appears.



    However, in 2016, there was a proposal to relax that restriction [Editor's note: P0266]. Note the strikethrough of paragraph 4 in section 4 of the paper. And thus was born requires requires.



    To tell the truth, I had never actually implemented that restriction in GCC, so it had always been possible. I think that Walter may have discovered that and found it useful, leading to that paper.



    Lest anybody think that I wasn't sensitive to writing requires twice, I did spend some time trying to determine if that could be simplified. Short answer: no.



    The problem is that there are two grammatical constructs that need to introduced after a template parameter list: very commonly a constraint expression (like P && Q) and occasionally syntactic requirements (like requires (T a) { ... }). That's called a requires-expression.



    The first requires introduces the constraint. The second requires introduces the requires-expression. That's just the way the grammar composes. I don't find it confusing at all.



    I tried, at one point, to collapse these to a single requires. Unfortunately, that leads to some seriously difficult parsing problems. You can't easily tell, for example if a ( after the requires denotes a nested subexpression or a parameter-list. I don't believe that there is a perfect disambiguation of those syntaxes (see the rationale for uniform initialization syntax; this problem is there too).



    So you make a choice: make requires introduce an expression (as it does now) or make it introduce a parameterized list of requirements.



    I chose the current approach because most of the time (as in nearly 100% of the time), I want something other than a requires-expression. And in the exceedingly rare case I did want a requires-expression for ad hoc constraints, I really don't mind writing the word twice. It's a an obvious indicator that I haven't developed a sufficiently sound abstraction for the template. (Because if I had, it would have a name.)



    I could have chosen to make the requires introduce a requires-expression. That's actually worse, because practically all of your constraints would start to look like this:



    template<typename T>
    requires { requires Eq<T>; }
    void f(T a, T b);


    Here, the 2nd requires is called a nested-requirement; it evaluates its expression (other code in the block of the requires-expression is not evaluated). I think this is way worse than the status quo. Now, you get to write requires twice everywhere.



    I could also have used more keywords. This is a problem in its own right---and it's not just bike shedding. There might be a way to "redistribute" keywords to avoid the duplication, but I haven't given that serious thought. But that doesn't really change the essence of the problem.







    share|improve this answer






























      9














      I found a comment from Andrew Sutton (one of the Concepts authors, who implemented it in gcc) to be quite helpful in this regard, so I thought I'd just quote it here in its near-entirety:




      Not so long ago requires-expressions (the phrase introduced by the second requires) was not allowed in constraint-expressions (the phrase introduced by the first requires). It could only appear in concept definitions. In fact, this is exactly what is proposed in the section of that paper where that claim appears.



      However, in 2016, there was a proposal to relax that restriction [Editor's note: P0266]. Note the strikethrough of paragraph 4 in section 4 of the paper. And thus was born requires requires.



      To tell the truth, I had never actually implemented that restriction in GCC, so it had always been possible. I think that Walter may have discovered that and found it useful, leading to that paper.



      Lest anybody think that I wasn't sensitive to writing requires twice, I did spend some time trying to determine if that could be simplified. Short answer: no.



      The problem is that there are two grammatical constructs that need to introduced after a template parameter list: very commonly a constraint expression (like P && Q) and occasionally syntactic requirements (like requires (T a) { ... }). That's called a requires-expression.



      The first requires introduces the constraint. The second requires introduces the requires-expression. That's just the way the grammar composes. I don't find it confusing at all.



      I tried, at one point, to collapse these to a single requires. Unfortunately, that leads to some seriously difficult parsing problems. You can't easily tell, for example if a ( after the requires denotes a nested subexpression or a parameter-list. I don't believe that there is a perfect disambiguation of those syntaxes (see the rationale for uniform initialization syntax; this problem is there too).



      So you make a choice: make requires introduce an expression (as it does now) or make it introduce a parameterized list of requirements.



      I chose the current approach because most of the time (as in nearly 100% of the time), I want something other than a requires-expression. And in the exceedingly rare case I did want a requires-expression for ad hoc constraints, I really don't mind writing the word twice. It's a an obvious indicator that I haven't developed a sufficiently sound abstraction for the template. (Because if I had, it would have a name.)



      I could have chosen to make the requires introduce a requires-expression. That's actually worse, because practically all of your constraints would start to look like this:



      template<typename T>
      requires { requires Eq<T>; }
      void f(T a, T b);


      Here, the 2nd requires is called a nested-requirement; it evaluates its expression (other code in the block of the requires-expression is not evaluated). I think this is way worse than the status quo. Now, you get to write requires twice everywhere.



      I could also have used more keywords. This is a problem in its own right---and it's not just bike shedding. There might be a way to "redistribute" keywords to avoid the duplication, but I haven't given that serious thought. But that doesn't really change the essence of the problem.







      share|improve this answer




























        9












        9








        9







        I found a comment from Andrew Sutton (one of the Concepts authors, who implemented it in gcc) to be quite helpful in this regard, so I thought I'd just quote it here in its near-entirety:




        Not so long ago requires-expressions (the phrase introduced by the second requires) was not allowed in constraint-expressions (the phrase introduced by the first requires). It could only appear in concept definitions. In fact, this is exactly what is proposed in the section of that paper where that claim appears.



        However, in 2016, there was a proposal to relax that restriction [Editor's note: P0266]. Note the strikethrough of paragraph 4 in section 4 of the paper. And thus was born requires requires.



        To tell the truth, I had never actually implemented that restriction in GCC, so it had always been possible. I think that Walter may have discovered that and found it useful, leading to that paper.



        Lest anybody think that I wasn't sensitive to writing requires twice, I did spend some time trying to determine if that could be simplified. Short answer: no.



        The problem is that there are two grammatical constructs that need to introduced after a template parameter list: very commonly a constraint expression (like P && Q) and occasionally syntactic requirements (like requires (T a) { ... }). That's called a requires-expression.



        The first requires introduces the constraint. The second requires introduces the requires-expression. That's just the way the grammar composes. I don't find it confusing at all.



        I tried, at one point, to collapse these to a single requires. Unfortunately, that leads to some seriously difficult parsing problems. You can't easily tell, for example if a ( after the requires denotes a nested subexpression or a parameter-list. I don't believe that there is a perfect disambiguation of those syntaxes (see the rationale for uniform initialization syntax; this problem is there too).



        So you make a choice: make requires introduce an expression (as it does now) or make it introduce a parameterized list of requirements.



        I chose the current approach because most of the time (as in nearly 100% of the time), I want something other than a requires-expression. And in the exceedingly rare case I did want a requires-expression for ad hoc constraints, I really don't mind writing the word twice. It's a an obvious indicator that I haven't developed a sufficiently sound abstraction for the template. (Because if I had, it would have a name.)



        I could have chosen to make the requires introduce a requires-expression. That's actually worse, because practically all of your constraints would start to look like this:



        template<typename T>
        requires { requires Eq<T>; }
        void f(T a, T b);


        Here, the 2nd requires is called a nested-requirement; it evaluates its expression (other code in the block of the requires-expression is not evaluated). I think this is way worse than the status quo. Now, you get to write requires twice everywhere.



        I could also have used more keywords. This is a problem in its own right---and it's not just bike shedding. There might be a way to "redistribute" keywords to avoid the duplication, but I haven't given that serious thought. But that doesn't really change the essence of the problem.







        share|improve this answer















        I found a comment from Andrew Sutton (one of the Concepts authors, who implemented it in gcc) to be quite helpful in this regard, so I thought I'd just quote it here in its near-entirety:




        Not so long ago requires-expressions (the phrase introduced by the second requires) was not allowed in constraint-expressions (the phrase introduced by the first requires). It could only appear in concept definitions. In fact, this is exactly what is proposed in the section of that paper where that claim appears.



        However, in 2016, there was a proposal to relax that restriction [Editor's note: P0266]. Note the strikethrough of paragraph 4 in section 4 of the paper. And thus was born requires requires.



        To tell the truth, I had never actually implemented that restriction in GCC, so it had always been possible. I think that Walter may have discovered that and found it useful, leading to that paper.



        Lest anybody think that I wasn't sensitive to writing requires twice, I did spend some time trying to determine if that could be simplified. Short answer: no.



        The problem is that there are two grammatical constructs that need to introduced after a template parameter list: very commonly a constraint expression (like P && Q) and occasionally syntactic requirements (like requires (T a) { ... }). That's called a requires-expression.



        The first requires introduces the constraint. The second requires introduces the requires-expression. That's just the way the grammar composes. I don't find it confusing at all.



        I tried, at one point, to collapse these to a single requires. Unfortunately, that leads to some seriously difficult parsing problems. You can't easily tell, for example if a ( after the requires denotes a nested subexpression or a parameter-list. I don't believe that there is a perfect disambiguation of those syntaxes (see the rationale for uniform initialization syntax; this problem is there too).



        So you make a choice: make requires introduce an expression (as it does now) or make it introduce a parameterized list of requirements.



        I chose the current approach because most of the time (as in nearly 100% of the time), I want something other than a requires-expression. And in the exceedingly rare case I did want a requires-expression for ad hoc constraints, I really don't mind writing the word twice. It's a an obvious indicator that I haven't developed a sufficiently sound abstraction for the template. (Because if I had, it would have a name.)



        I could have chosen to make the requires introduce a requires-expression. That's actually worse, because practically all of your constraints would start to look like this:



        template<typename T>
        requires { requires Eq<T>; }
        void f(T a, T b);


        Here, the 2nd requires is called a nested-requirement; it evaluates its expression (other code in the block of the requires-expression is not evaluated). I think this is way worse than the status quo. Now, you get to write requires twice everywhere.



        I could also have used more keywords. This is a problem in its own right---and it's not just bike shedding. There might be a way to "redistribute" keywords to avoid the duplication, but I haven't given that serious thought. But that doesn't really change the essence of the problem.








        share|improve this answer














        share|improve this answer



        share|improve this answer








        answered Jan 16 at 15:30


























        community wiki





        Barry
























            -9














            Because you are saying that a thing A has a requirement B, and the requirement B has a requirement C.



            The thing A requires B which in turn requires C.



            The "requires" clause itself requires something.



            You have thing A (requiring B (requiring C)).



            Meh. :)






            share|improve this answer



















            • 3





              But according to the other answers, the first and second requires are not conceptually the same thing (one is a clause, one an expression). In fact, if I understand correctly, the two sets of () in requires (requires (T x) { x + x; }) have very different meanings (the outer being optional and always containing a boolean constexpr; the inner being a mandatory part of introducing a requires expression and not allowing actual expressions).

              – Max Langhof
              Jan 15 at 15:28








            • 2





              @MaxLanghof Are you saying that the requirements differ? :D

              – Lightness Races in Orbit
              Jan 15 at 15:42
















            -9














            Because you are saying that a thing A has a requirement B, and the requirement B has a requirement C.



            The thing A requires B which in turn requires C.



            The "requires" clause itself requires something.



            You have thing A (requiring B (requiring C)).



            Meh. :)






            share|improve this answer



















            • 3





              But according to the other answers, the first and second requires are not conceptually the same thing (one is a clause, one an expression). In fact, if I understand correctly, the two sets of () in requires (requires (T x) { x + x; }) have very different meanings (the outer being optional and always containing a boolean constexpr; the inner being a mandatory part of introducing a requires expression and not allowing actual expressions).

              – Max Langhof
              Jan 15 at 15:28








            • 2





              @MaxLanghof Are you saying that the requirements differ? :D

              – Lightness Races in Orbit
              Jan 15 at 15:42














            -9












            -9








            -9







            Because you are saying that a thing A has a requirement B, and the requirement B has a requirement C.



            The thing A requires B which in turn requires C.



            The "requires" clause itself requires something.



            You have thing A (requiring B (requiring C)).



            Meh. :)






            share|improve this answer













            Because you are saying that a thing A has a requirement B, and the requirement B has a requirement C.



            The thing A requires B which in turn requires C.



            The "requires" clause itself requires something.



            You have thing A (requiring B (requiring C)).



            Meh. :)







            share|improve this answer












            share|improve this answer



            share|improve this answer










            answered Jan 15 at 15:18









            Lightness Races in OrbitLightness Races in Orbit

            289k51470798




            289k51470798








            • 3





              But according to the other answers, the first and second requires are not conceptually the same thing (one is a clause, one an expression). In fact, if I understand correctly, the two sets of () in requires (requires (T x) { x + x; }) have very different meanings (the outer being optional and always containing a boolean constexpr; the inner being a mandatory part of introducing a requires expression and not allowing actual expressions).

              – Max Langhof
              Jan 15 at 15:28








            • 2





              @MaxLanghof Are you saying that the requirements differ? :D

              – Lightness Races in Orbit
              Jan 15 at 15:42














            • 3





              But according to the other answers, the first and second requires are not conceptually the same thing (one is a clause, one an expression). In fact, if I understand correctly, the two sets of () in requires (requires (T x) { x + x; }) have very different meanings (the outer being optional and always containing a boolean constexpr; the inner being a mandatory part of introducing a requires expression and not allowing actual expressions).

              – Max Langhof
              Jan 15 at 15:28








            • 2





              @MaxLanghof Are you saying that the requirements differ? :D

              – Lightness Races in Orbit
              Jan 15 at 15:42








            3




            3





            But according to the other answers, the first and second requires are not conceptually the same thing (one is a clause, one an expression). In fact, if I understand correctly, the two sets of () in requires (requires (T x) { x + x; }) have very different meanings (the outer being optional and always containing a boolean constexpr; the inner being a mandatory part of introducing a requires expression and not allowing actual expressions).

            – Max Langhof
            Jan 15 at 15:28







            But according to the other answers, the first and second requires are not conceptually the same thing (one is a clause, one an expression). In fact, if I understand correctly, the two sets of () in requires (requires (T x) { x + x; }) have very different meanings (the outer being optional and always containing a boolean constexpr; the inner being a mandatory part of introducing a requires expression and not allowing actual expressions).

            – Max Langhof
            Jan 15 at 15:28






            2




            2





            @MaxLanghof Are you saying that the requirements differ? :D

            – Lightness Races in Orbit
            Jan 15 at 15:42





            @MaxLanghof Are you saying that the requirements differ? :D

            – Lightness Races in Orbit
            Jan 15 at 15:42


















            draft saved

            draft discarded




















































            Thanks for contributing an answer to Stack Overflow!


            • Please be sure to answer the question. Provide details and share your research!

            But avoid



            • Asking for help, clarification, or responding to other answers.

            • Making statements based on opinion; back them up with references or personal experience.


            To learn more, see our tips on writing great answers.




            draft saved


            draft discarded














            StackExchange.ready(
            function () {
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f54200988%2fwhy-do-we-require-requires-requires%23new-answer', 'question_page');
            }
            );

            Post as a guest















            Required, but never shown





















































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown

































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown







            Popular posts from this blog

            Mario Kart Wii

            What does “Dominus providebit” mean?

            Antonio Litta Visconti Arese