constexpr function with unused reference argument – gcc vs clang





.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty{ height:90px;width:728px;box-sizing:border-box;
}







7















Consider the following code:



template <int N, typename T> void f(T) { }

template <typename T>
constexpr int k(T&) { return 0; }

int main()
{
constexpr auto i = 1;
f<k(i)>([&i]
{
f<k(i)>(0);
});
}


clang++ (trunk) compiles it. g++ (trunk) fails with the following error:




<source>: In lambda function:

<source>:11:19: error: no matching function for call to 'f<k<const int>((* & i))>(int)'
11 | f<k(i)>(0);
| ^

<source>:1:35: note: candidate: 'template<int N, class T> void f(T)'
1 | template <int N, typename T> void f(T) { }
| ^

<source>:1:35: note: template argument deduction/substitution failed:

<source>:11:19: error: '__closure' is not a constant expression
11 | f<k(i)>(0);
| ^

<source>:11:13: note: in template argument for type 'int'
11 | f<k(i)>(0);
| ~^~~



live example on godbolt.org





Changing k(T&) to k(T) solves the issue. It seems to me that the problem is related to the fact that the reference argument is not a constant expression, but it not used as part of k.



What compiler is correct here?










share|improve this question




















  • 2





    Related: GCC and Clang disagree about C++17 constexpr lambda captures. T.C.'s answer also answers your question.

    – xskxzr
    Dec 30 '18 at 16:16




















7















Consider the following code:



template <int N, typename T> void f(T) { }

template <typename T>
constexpr int k(T&) { return 0; }

int main()
{
constexpr auto i = 1;
f<k(i)>([&i]
{
f<k(i)>(0);
});
}


clang++ (trunk) compiles it. g++ (trunk) fails with the following error:




<source>: In lambda function:

<source>:11:19: error: no matching function for call to 'f<k<const int>((* & i))>(int)'
11 | f<k(i)>(0);
| ^

<source>:1:35: note: candidate: 'template<int N, class T> void f(T)'
1 | template <int N, typename T> void f(T) { }
| ^

<source>:1:35: note: template argument deduction/substitution failed:

<source>:11:19: error: '__closure' is not a constant expression
11 | f<k(i)>(0);
| ^

<source>:11:13: note: in template argument for type 'int'
11 | f<k(i)>(0);
| ~^~~



live example on godbolt.org





Changing k(T&) to k(T) solves the issue. It seems to me that the problem is related to the fact that the reference argument is not a constant expression, but it not used as part of k.



What compiler is correct here?










share|improve this question




















  • 2





    Related: GCC and Clang disagree about C++17 constexpr lambda captures. T.C.'s answer also answers your question.

    – xskxzr
    Dec 30 '18 at 16:16
















7












7








7








Consider the following code:



template <int N, typename T> void f(T) { }

template <typename T>
constexpr int k(T&) { return 0; }

int main()
{
constexpr auto i = 1;
f<k(i)>([&i]
{
f<k(i)>(0);
});
}


clang++ (trunk) compiles it. g++ (trunk) fails with the following error:




<source>: In lambda function:

<source>:11:19: error: no matching function for call to 'f<k<const int>((* & i))>(int)'
11 | f<k(i)>(0);
| ^

<source>:1:35: note: candidate: 'template<int N, class T> void f(T)'
1 | template <int N, typename T> void f(T) { }
| ^

<source>:1:35: note: template argument deduction/substitution failed:

<source>:11:19: error: '__closure' is not a constant expression
11 | f<k(i)>(0);
| ^

<source>:11:13: note: in template argument for type 'int'
11 | f<k(i)>(0);
| ~^~~



live example on godbolt.org





Changing k(T&) to k(T) solves the issue. It seems to me that the problem is related to the fact that the reference argument is not a constant expression, but it not used as part of k.



What compiler is correct here?










share|improve this question
















Consider the following code:



template <int N, typename T> void f(T) { }

template <typename T>
constexpr int k(T&) { return 0; }

int main()
{
constexpr auto i = 1;
f<k(i)>([&i]
{
f<k(i)>(0);
});
}


clang++ (trunk) compiles it. g++ (trunk) fails with the following error:




<source>: In lambda function:

<source>:11:19: error: no matching function for call to 'f<k<const int>((* & i))>(int)'
11 | f<k(i)>(0);
| ^

<source>:1:35: note: candidate: 'template<int N, class T> void f(T)'
1 | template <int N, typename T> void f(T) { }
| ^

<source>:1:35: note: template argument deduction/substitution failed:

<source>:11:19: error: '__closure' is not a constant expression
11 | f<k(i)>(0);
| ^

<source>:11:13: note: in template argument for type 'int'
11 | f<k(i)>(0);
| ~^~~



live example on godbolt.org





Changing k(T&) to k(T) solves the issue. It seems to me that the problem is related to the fact that the reference argument is not a constant expression, but it not used as part of k.



What compiler is correct here?







c++ templates language-lawyer c++17 constexpr






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Dec 30 '18 at 13:40









Baum mit Augen

41.7k12120156




41.7k12120156










asked Dec 30 '18 at 13:29









Vittorio RomeoVittorio Romeo

60k17166310




60k17166310








  • 2





    Related: GCC and Clang disagree about C++17 constexpr lambda captures. T.C.'s answer also answers your question.

    – xskxzr
    Dec 30 '18 at 16:16
















  • 2





    Related: GCC and Clang disagree about C++17 constexpr lambda captures. T.C.'s answer also answers your question.

    – xskxzr
    Dec 30 '18 at 16:16










2




2





Related: GCC and Clang disagree about C++17 constexpr lambda captures. T.C.'s answer also answers your question.

– xskxzr
Dec 30 '18 at 16:16







Related: GCC and Clang disagree about C++17 constexpr lambda captures. T.C.'s answer also answers your question.

– xskxzr
Dec 30 '18 at 16:16














3 Answers
3






active

oldest

votes


















5














GCC is correct here.



According to [expr.const]/4:




An expression e is a core constant expression unless the evaluation
of e, following the rules of the abstract machine, would evaluate
one of the following expressions:




  • ...

  • in a lambda-expression, a reference to [...] a variable with automatic storage duration defined outside that lambda-expression,
    where the reference would be an odr-use; ...

  • ...




k(i) odr-uses i thus k(i) is not a constant expression in the lambda expression, so this code is ill-formed.






share|improve this answer































    0














    The error is emitted for the expression k(i) that appears within the lambda expression compound statements but not outside it. This is a GCC bug. According to [expr.prim.lambda.capture]/11




    An id-expression within the compound-statement of a lambda-expression that is an odr-use of a reference captured by reference refers to the entity to which the captured reference is bound and not to the captured reference.




    So k(i) outside the lambda is the same expression as k(i) outside the lambda, so there is no reason for GCC to emit an error for the second expression but not for the first.






    share|improve this answer































      -1














      Compiled with 0 errors on godbolt.



      I used a variable result_k = k(i); for bypass this errors.



      template <int N, typename T> void f(T) { }

      template <typename T> constexpr int k(T&) { return 0; }

      int main() {
      constexpr auto i = 1;
      const int result_k=k(i);
      f<result_k>([&i]{ f<result_k>(0);});
      }





      share|improve this answer


























      • Rewrited code, the last code is not correct.

        – Andreadjk
        Dec 30 '18 at 15:48






      • 3





        This question is asking which compiler is correct, rather than how to resolve the issue.

        – xskxzr
        Dec 30 '18 at 16:26











      • clang++ (trunk) compiles it. g++ (trunk) fails with the following error: I posted the code beacause the owner use two compilers.. clang and g++, this code work with clag++ and g++

        – Andreadjk
        Dec 30 '18 at 17:41








      • 2





        And yes, that is a answer, but not the one the OP wants to know. This is question is tagged language-laywer and OP asks which compiler is correct, not how to fix it. An good answer would be telling OP whether clang or gcc is right, which yours does not do.

        – Rakete1111
        Dec 30 '18 at 20:37












      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%2f53978006%2fconstexpr-function-with-unused-reference-argument-gcc-vs-clang%23new-answer', 'question_page');
      }
      );

      Post as a guest















      Required, but never shown

























      3 Answers
      3






      active

      oldest

      votes








      3 Answers
      3






      active

      oldest

      votes









      active

      oldest

      votes






      active

      oldest

      votes









      5














      GCC is correct here.



      According to [expr.const]/4:




      An expression e is a core constant expression unless the evaluation
      of e, following the rules of the abstract machine, would evaluate
      one of the following expressions:




      • ...

      • in a lambda-expression, a reference to [...] a variable with automatic storage duration defined outside that lambda-expression,
        where the reference would be an odr-use; ...

      • ...




      k(i) odr-uses i thus k(i) is not a constant expression in the lambda expression, so this code is ill-formed.






      share|improve this answer




























        5














        GCC is correct here.



        According to [expr.const]/4:




        An expression e is a core constant expression unless the evaluation
        of e, following the rules of the abstract machine, would evaluate
        one of the following expressions:




        • ...

        • in a lambda-expression, a reference to [...] a variable with automatic storage duration defined outside that lambda-expression,
          where the reference would be an odr-use; ...

        • ...




        k(i) odr-uses i thus k(i) is not a constant expression in the lambda expression, so this code is ill-formed.






        share|improve this answer


























          5












          5








          5







          GCC is correct here.



          According to [expr.const]/4:




          An expression e is a core constant expression unless the evaluation
          of e, following the rules of the abstract machine, would evaluate
          one of the following expressions:




          • ...

          • in a lambda-expression, a reference to [...] a variable with automatic storage duration defined outside that lambda-expression,
            where the reference would be an odr-use; ...

          • ...




          k(i) odr-uses i thus k(i) is not a constant expression in the lambda expression, so this code is ill-formed.






          share|improve this answer













          GCC is correct here.



          According to [expr.const]/4:




          An expression e is a core constant expression unless the evaluation
          of e, following the rules of the abstract machine, would evaluate
          one of the following expressions:




          • ...

          • in a lambda-expression, a reference to [...] a variable with automatic storage duration defined outside that lambda-expression,
            where the reference would be an odr-use; ...

          • ...




          k(i) odr-uses i thus k(i) is not a constant expression in the lambda expression, so this code is ill-formed.







          share|improve this answer












          share|improve this answer



          share|improve this answer










          answered Dec 30 '18 at 16:23









          xskxzrxskxzr

          7,22992558




          7,22992558

























              0














              The error is emitted for the expression k(i) that appears within the lambda expression compound statements but not outside it. This is a GCC bug. According to [expr.prim.lambda.capture]/11




              An id-expression within the compound-statement of a lambda-expression that is an odr-use of a reference captured by reference refers to the entity to which the captured reference is bound and not to the captured reference.




              So k(i) outside the lambda is the same expression as k(i) outside the lambda, so there is no reason for GCC to emit an error for the second expression but not for the first.






              share|improve this answer




























                0














                The error is emitted for the expression k(i) that appears within the lambda expression compound statements but not outside it. This is a GCC bug. According to [expr.prim.lambda.capture]/11




                An id-expression within the compound-statement of a lambda-expression that is an odr-use of a reference captured by reference refers to the entity to which the captured reference is bound and not to the captured reference.




                So k(i) outside the lambda is the same expression as k(i) outside the lambda, so there is no reason for GCC to emit an error for the second expression but not for the first.






                share|improve this answer


























                  0












                  0








                  0







                  The error is emitted for the expression k(i) that appears within the lambda expression compound statements but not outside it. This is a GCC bug. According to [expr.prim.lambda.capture]/11




                  An id-expression within the compound-statement of a lambda-expression that is an odr-use of a reference captured by reference refers to the entity to which the captured reference is bound and not to the captured reference.




                  So k(i) outside the lambda is the same expression as k(i) outside the lambda, so there is no reason for GCC to emit an error for the second expression but not for the first.






                  share|improve this answer













                  The error is emitted for the expression k(i) that appears within the lambda expression compound statements but not outside it. This is a GCC bug. According to [expr.prim.lambda.capture]/11




                  An id-expression within the compound-statement of a lambda-expression that is an odr-use of a reference captured by reference refers to the entity to which the captured reference is bound and not to the captured reference.




                  So k(i) outside the lambda is the same expression as k(i) outside the lambda, so there is no reason for GCC to emit an error for the second expression but not for the first.







                  share|improve this answer












                  share|improve this answer



                  share|improve this answer










                  answered Dec 30 '18 at 14:33









                  OlivOliv

                  9,4271957




                  9,4271957























                      -1














                      Compiled with 0 errors on godbolt.



                      I used a variable result_k = k(i); for bypass this errors.



                      template <int N, typename T> void f(T) { }

                      template <typename T> constexpr int k(T&) { return 0; }

                      int main() {
                      constexpr auto i = 1;
                      const int result_k=k(i);
                      f<result_k>([&i]{ f<result_k>(0);});
                      }





                      share|improve this answer


























                      • Rewrited code, the last code is not correct.

                        – Andreadjk
                        Dec 30 '18 at 15:48






                      • 3





                        This question is asking which compiler is correct, rather than how to resolve the issue.

                        – xskxzr
                        Dec 30 '18 at 16:26











                      • clang++ (trunk) compiles it. g++ (trunk) fails with the following error: I posted the code beacause the owner use two compilers.. clang and g++, this code work with clag++ and g++

                        – Andreadjk
                        Dec 30 '18 at 17:41








                      • 2





                        And yes, that is a answer, but not the one the OP wants to know. This is question is tagged language-laywer and OP asks which compiler is correct, not how to fix it. An good answer would be telling OP whether clang or gcc is right, which yours does not do.

                        – Rakete1111
                        Dec 30 '18 at 20:37
















                      -1














                      Compiled with 0 errors on godbolt.



                      I used a variable result_k = k(i); for bypass this errors.



                      template <int N, typename T> void f(T) { }

                      template <typename T> constexpr int k(T&) { return 0; }

                      int main() {
                      constexpr auto i = 1;
                      const int result_k=k(i);
                      f<result_k>([&i]{ f<result_k>(0);});
                      }





                      share|improve this answer


























                      • Rewrited code, the last code is not correct.

                        – Andreadjk
                        Dec 30 '18 at 15:48






                      • 3





                        This question is asking which compiler is correct, rather than how to resolve the issue.

                        – xskxzr
                        Dec 30 '18 at 16:26











                      • clang++ (trunk) compiles it. g++ (trunk) fails with the following error: I posted the code beacause the owner use two compilers.. clang and g++, this code work with clag++ and g++

                        – Andreadjk
                        Dec 30 '18 at 17:41








                      • 2





                        And yes, that is a answer, but not the one the OP wants to know. This is question is tagged language-laywer and OP asks which compiler is correct, not how to fix it. An good answer would be telling OP whether clang or gcc is right, which yours does not do.

                        – Rakete1111
                        Dec 30 '18 at 20:37














                      -1












                      -1








                      -1







                      Compiled with 0 errors on godbolt.



                      I used a variable result_k = k(i); for bypass this errors.



                      template <int N, typename T> void f(T) { }

                      template <typename T> constexpr int k(T&) { return 0; }

                      int main() {
                      constexpr auto i = 1;
                      const int result_k=k(i);
                      f<result_k>([&i]{ f<result_k>(0);});
                      }





                      share|improve this answer















                      Compiled with 0 errors on godbolt.



                      I used a variable result_k = k(i); for bypass this errors.



                      template <int N, typename T> void f(T) { }

                      template <typename T> constexpr int k(T&) { return 0; }

                      int main() {
                      constexpr auto i = 1;
                      const int result_k=k(i);
                      f<result_k>([&i]{ f<result_k>(0);});
                      }






                      share|improve this answer














                      share|improve this answer



                      share|improve this answer








                      edited Dec 30 '18 at 16:26









                      xskxzr

                      7,22992558




                      7,22992558










                      answered Dec 30 '18 at 14:56









                      AndreadjkAndreadjk

                      11




                      11













                      • Rewrited code, the last code is not correct.

                        – Andreadjk
                        Dec 30 '18 at 15:48






                      • 3





                        This question is asking which compiler is correct, rather than how to resolve the issue.

                        – xskxzr
                        Dec 30 '18 at 16:26











                      • clang++ (trunk) compiles it. g++ (trunk) fails with the following error: I posted the code beacause the owner use two compilers.. clang and g++, this code work with clag++ and g++

                        – Andreadjk
                        Dec 30 '18 at 17:41








                      • 2





                        And yes, that is a answer, but not the one the OP wants to know. This is question is tagged language-laywer and OP asks which compiler is correct, not how to fix it. An good answer would be telling OP whether clang or gcc is right, which yours does not do.

                        – Rakete1111
                        Dec 30 '18 at 20:37



















                      • Rewrited code, the last code is not correct.

                        – Andreadjk
                        Dec 30 '18 at 15:48






                      • 3





                        This question is asking which compiler is correct, rather than how to resolve the issue.

                        – xskxzr
                        Dec 30 '18 at 16:26











                      • clang++ (trunk) compiles it. g++ (trunk) fails with the following error: I posted the code beacause the owner use two compilers.. clang and g++, this code work with clag++ and g++

                        – Andreadjk
                        Dec 30 '18 at 17:41








                      • 2





                        And yes, that is a answer, but not the one the OP wants to know. This is question is tagged language-laywer and OP asks which compiler is correct, not how to fix it. An good answer would be telling OP whether clang or gcc is right, which yours does not do.

                        – Rakete1111
                        Dec 30 '18 at 20:37

















                      Rewrited code, the last code is not correct.

                      – Andreadjk
                      Dec 30 '18 at 15:48





                      Rewrited code, the last code is not correct.

                      – Andreadjk
                      Dec 30 '18 at 15:48




                      3




                      3





                      This question is asking which compiler is correct, rather than how to resolve the issue.

                      – xskxzr
                      Dec 30 '18 at 16:26





                      This question is asking which compiler is correct, rather than how to resolve the issue.

                      – xskxzr
                      Dec 30 '18 at 16:26













                      clang++ (trunk) compiles it. g++ (trunk) fails with the following error: I posted the code beacause the owner use two compilers.. clang and g++, this code work with clag++ and g++

                      – Andreadjk
                      Dec 30 '18 at 17:41







                      clang++ (trunk) compiles it. g++ (trunk) fails with the following error: I posted the code beacause the owner use two compilers.. clang and g++, this code work with clag++ and g++

                      – Andreadjk
                      Dec 30 '18 at 17:41






                      2




                      2





                      And yes, that is a answer, but not the one the OP wants to know. This is question is tagged language-laywer and OP asks which compiler is correct, not how to fix it. An good answer would be telling OP whether clang or gcc is right, which yours does not do.

                      – Rakete1111
                      Dec 30 '18 at 20:37





                      And yes, that is a answer, but not the one the OP wants to know. This is question is tagged language-laywer and OP asks which compiler is correct, not how to fix it. An good answer would be telling OP whether clang or gcc is right, which yours does not do.

                      – Rakete1111
                      Dec 30 '18 at 20:37


















                      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%2f53978006%2fconstexpr-function-with-unused-reference-argument-gcc-vs-clang%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

                      Bundesstraße 106

                      Le Mesnil-Réaume

                      Ida-Boy-Ed-Garten