constexpr function with unused reference argument – gcc vs clang












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
























  • Related: GCC and Clang disagree about C++17 constexpr lambda captures. T.C.'s answer also answers your question.
    – xskxzr
    2 hours ago


















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
























  • Related: GCC and Clang disagree about C++17 constexpr lambda captures. T.C.'s answer also answers your question.
    – xskxzr
    2 hours ago
















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 4 hours ago









Baum mit Augen

40.2k12115147




40.2k12115147










asked 4 hours ago









Vittorio Romeo

57.3k17154293




57.3k17154293












  • Related: GCC and Clang disagree about C++17 constexpr lambda captures. T.C.'s answer also answers your question.
    – xskxzr
    2 hours ago




















  • Related: GCC and Clang disagree about C++17 constexpr lambda captures. T.C.'s answer also answers your question.
    – xskxzr
    2 hours ago


















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






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














4 Answers
4






active

oldest

votes


















2














It's a GCC bug.




[expr.prim.lambda.capture]/13 - 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.




The expression inside the lambda that refer to k(i) must be equivalent to



 constexpr auto i = 1;        
constexpr auto j = k(i);


which is accepted by both compilers. There are in fact some GCC reports similar to your example, two of them are GCC-86429 and GCC-82643






share|improve this answer



















  • 1




    Where is the reference being captured?
    – xskxzr
    2 hours ago



















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














    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














      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










      New contributor




      Andreadjk is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
      Check out our Code of Conduct.


















      • Rewrited code, the last code is not correct.
        – Andreadjk
        2 hours ago






      • 1




        This question is asking which compiler is correct, rather than how to resolve the issue.
        – xskxzr
        1 hour ago










      • 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
        41 mins ago













      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

























      4 Answers
      4






      active

      oldest

      votes








      4 Answers
      4






      active

      oldest

      votes









      active

      oldest

      votes






      active

      oldest

      votes









      2














      It's a GCC bug.




      [expr.prim.lambda.capture]/13 - 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.




      The expression inside the lambda that refer to k(i) must be equivalent to



       constexpr auto i = 1;        
      constexpr auto j = k(i);


      which is accepted by both compilers. There are in fact some GCC reports similar to your example, two of them are GCC-86429 and GCC-82643






      share|improve this answer



















      • 1




        Where is the reference being captured?
        – xskxzr
        2 hours ago
















      2














      It's a GCC bug.




      [expr.prim.lambda.capture]/13 - 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.




      The expression inside the lambda that refer to k(i) must be equivalent to



       constexpr auto i = 1;        
      constexpr auto j = k(i);


      which is accepted by both compilers. There are in fact some GCC reports similar to your example, two of them are GCC-86429 and GCC-82643






      share|improve this answer



















      • 1




        Where is the reference being captured?
        – xskxzr
        2 hours ago














      2












      2








      2






      It's a GCC bug.




      [expr.prim.lambda.capture]/13 - 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.




      The expression inside the lambda that refer to k(i) must be equivalent to



       constexpr auto i = 1;        
      constexpr auto j = k(i);


      which is accepted by both compilers. There are in fact some GCC reports similar to your example, two of them are GCC-86429 and GCC-82643






      share|improve this answer














      It's a GCC bug.




      [expr.prim.lambda.capture]/13 - 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.




      The expression inside the lambda that refer to k(i) must be equivalent to



       constexpr auto i = 1;        
      constexpr auto j = k(i);


      which is accepted by both compilers. There are in fact some GCC reports similar to your example, two of them are GCC-86429 and GCC-82643







      share|improve this answer














      share|improve this answer



      share|improve this answer








      edited 3 hours ago

























      answered 3 hours ago









      Jans

      8,09522535




      8,09522535








      • 1




        Where is the reference being captured?
        – xskxzr
        2 hours ago














      • 1




        Where is the reference being captured?
        – xskxzr
        2 hours ago








      1




      1




      Where is the reference being captured?
      – xskxzr
      2 hours ago




      Where is the reference being captured?
      – xskxzr
      2 hours ago













      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 3 hours ago









          Oliv

          8,2501955




          8,2501955























              0














              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














                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












                  0








                  0






                  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 1 hour ago









                  xskxzr

                  6,04082052




                  6,04082052























                      0














                      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










                      New contributor




                      Andreadjk is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
                      Check out our Code of Conduct.


















                      • Rewrited code, the last code is not correct.
                        – Andreadjk
                        2 hours ago






                      • 1




                        This question is asking which compiler is correct, rather than how to resolve the issue.
                        – xskxzr
                        1 hour ago










                      • 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
                        41 mins ago


















                      0














                      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










                      New contributor




                      Andreadjk is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
                      Check out our Code of Conduct.


















                      • Rewrited code, the last code is not correct.
                        – Andreadjk
                        2 hours ago






                      • 1




                        This question is asking which compiler is correct, rather than how to resolve the issue.
                        – xskxzr
                        1 hour ago










                      • 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
                        41 mins ago
















                      0












                      0








                      0






                      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










                      New contributor




                      Andreadjk is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
                      Check out our Code of Conduct.









                      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










                      New contributor




                      Andreadjk is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
                      Check out our Code of Conduct.









                      share|improve this answer



                      share|improve this answer








                      edited 1 hour ago









                      xskxzr

                      6,04082052




                      6,04082052






                      New contributor




                      Andreadjk is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
                      Check out our Code of Conduct.









                      answered 3 hours ago









                      Andreadjk

                      11




                      11




                      New contributor




                      Andreadjk is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
                      Check out our Code of Conduct.





                      New contributor





                      Andreadjk is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
                      Check out our Code of Conduct.






                      Andreadjk is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
                      Check out our Code of Conduct.












                      • Rewrited code, the last code is not correct.
                        – Andreadjk
                        2 hours ago






                      • 1




                        This question is asking which compiler is correct, rather than how to resolve the issue.
                        – xskxzr
                        1 hour ago










                      • 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
                        41 mins ago




















                      • Rewrited code, the last code is not correct.
                        – Andreadjk
                        2 hours ago






                      • 1




                        This question is asking which compiler is correct, rather than how to resolve the issue.
                        – xskxzr
                        1 hour ago










                      • 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
                        41 mins ago


















                      Rewrited code, the last code is not correct.
                      – Andreadjk
                      2 hours ago




                      Rewrited code, the last code is not correct.
                      – Andreadjk
                      2 hours ago




                      1




                      1




                      This question is asking which compiler is correct, rather than how to resolve the issue.
                      – xskxzr
                      1 hour ago




                      This question is asking which compiler is correct, rather than how to resolve the issue.
                      – xskxzr
                      1 hour ago












                      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
                      41 mins ago






                      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
                      41 mins ago




















                      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.





                      Some of your past answers have not been well-received, and you're in danger of being blocked from answering.


                      Please pay close attention to the following guidance:


                      • 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

                      Morgemoulin

                      Scott Moir

                      Souastre