Constexpr variable captured inside lambda loses its constexpr-ness2019 Community Moderator ElectionWhy can't non-static data members be constexpr?Is a compiler forced to reject invalid constexpr?Why is this constexpr static member function not seen as constexpr when called?Cannot create static constexprWhy is it not legal to access global non constant variable in constexpr non member functionCannot compile constexpr member function with GCC 4.9C++17 if constexpr() usage with tupleif constexpr in a recursive generic lambda: different compiler behaviorAccess to constexpr variable inside lambda expression without capturingMSVS2017 error “expression did not evaluate to a constant” when compile constexpr with lambdaC++ “forgetting” that variable is constexpr when used as function argument

Exposing a company lying about themselves in a tightly knit industry: Is my career at risk on the long run?

How do researchers send unsolicited emails asking for feedback on their works?

Why does Surtur say that Thor is Asgard's doom?

Are hand made posters acceptable in Academia?

PTIJ: At the Passover Seder, is one allowed to speak more than once during Maggid?

When did hardware antialiasing start being available?

Does convergence of polynomials imply that of its coefficients?

PTIJ: Which Dr. Seuss books should one obtain?

Help with identifying unique aircraft over NE Pennsylvania

Fair way to split coins

Single word to change groups

Symbolism of 18 Journeyers

Air travel with refrigerated insulin

is this saw blade faulty?

Gauss brackets with double vertical lines

"Marked down as someone wanting to sell shares." What does that mean?

What is it called when someone votes for an option that's not their first choice?

Do native speakers use "ultima" and "proxima" frequently in spoken English?

Homology of the fiber

When should a starting writer get his own webpage?

Asserting that Atheism and Theism are both faith based positions

Why do I have a large white artefact on the rendered image?

Why is this tree refusing to shed its dead leaves?

Do I need an EFI partition for each 18.04 ubuntu I have on my HD?



Constexpr variable captured inside lambda loses its constexpr-ness



2019 Community Moderator ElectionWhy can't non-static data members be constexpr?Is a compiler forced to reject invalid constexpr?Why is this constexpr static member function not seen as constexpr when called?Cannot create static constexprWhy is it not legal to access global non constant variable in constexpr non member functionCannot compile constexpr member function with GCC 4.9C++17 if constexpr() usage with tupleif constexpr in a recursive generic lambda: different compiler behaviorAccess to constexpr variable inside lambda expression without capturingMSVS2017 error “expression did not evaluate to a constant” when compile constexpr with lambdaC++ “forgetting” that variable is constexpr when used as function argument










18















This code compiles fine in g++ (coliru), but not MSVC (godbolt and my VS2017).



#include <type_traits>
#include <iostream>
template<class T> void f()
constexpr bool b=std::is_same_v<T,int>; //#1
auto func_x=[&]()
if constexpr(b) //#error
else

;
func_x();

int main()
f<int>();




(6): error C2131: expression did not evaluate to a constant

(6): note: failure was caused by a read of a variable outside its lifetime

(6): note: see usage of 'this'




Which one (g++ or MSVC) is wrong?

What is this in "see usage of 'this'"??



How to work around it while keep the compile-time guarantee?



In my real case, b (#1) is a complex statement depends on a few other constexpr variables.










share|improve this question
























  • Coliru uses GCC 8.2; GCC 8.3 from gcc.godbolt.org also rejects the code. Clang 7.0.0 compiles it.

    – HolyBlackCat
    Mar 13 at 7:29















18















This code compiles fine in g++ (coliru), but not MSVC (godbolt and my VS2017).



#include <type_traits>
#include <iostream>
template<class T> void f()
constexpr bool b=std::is_same_v<T,int>; //#1
auto func_x=[&]()
if constexpr(b) //#error
else

;
func_x();

int main()
f<int>();




(6): error C2131: expression did not evaluate to a constant

(6): note: failure was caused by a read of a variable outside its lifetime

(6): note: see usage of 'this'




Which one (g++ or MSVC) is wrong?

What is this in "see usage of 'this'"??



How to work around it while keep the compile-time guarantee?



In my real case, b (#1) is a complex statement depends on a few other constexpr variables.










share|improve this question
























  • Coliru uses GCC 8.2; GCC 8.3 from gcc.godbolt.org also rejects the code. Clang 7.0.0 compiles it.

    – HolyBlackCat
    Mar 13 at 7:29













18












18








18








This code compiles fine in g++ (coliru), but not MSVC (godbolt and my VS2017).



#include <type_traits>
#include <iostream>
template<class T> void f()
constexpr bool b=std::is_same_v<T,int>; //#1
auto func_x=[&]()
if constexpr(b) //#error
else

;
func_x();

int main()
f<int>();




(6): error C2131: expression did not evaluate to a constant

(6): note: failure was caused by a read of a variable outside its lifetime

(6): note: see usage of 'this'




Which one (g++ or MSVC) is wrong?

What is this in "see usage of 'this'"??



How to work around it while keep the compile-time guarantee?



In my real case, b (#1) is a complex statement depends on a few other constexpr variables.










share|improve this question
















This code compiles fine in g++ (coliru), but not MSVC (godbolt and my VS2017).



#include <type_traits>
#include <iostream>
template<class T> void f()
constexpr bool b=std::is_same_v<T,int>; //#1
auto func_x=[&]()
if constexpr(b) //#error
else

;
func_x();

int main()
f<int>();




(6): error C2131: expression did not evaluate to a constant

(6): note: failure was caused by a read of a variable outside its lifetime

(6): note: see usage of 'this'




Which one (g++ or MSVC) is wrong?

What is this in "see usage of 'this'"??



How to work around it while keep the compile-time guarantee?



In my real case, b (#1) is a complex statement depends on a few other constexpr variables.







c++ lambda language-lawyer c++17 if-constexpr






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Mar 13 at 7:30









HolyBlackCat

16.9k33568




16.9k33568










asked Mar 13 at 7:21









javaLoverjavaLover

2,7891939




2,7891939












  • Coliru uses GCC 8.2; GCC 8.3 from gcc.godbolt.org also rejects the code. Clang 7.0.0 compiles it.

    – HolyBlackCat
    Mar 13 at 7:29

















  • Coliru uses GCC 8.2; GCC 8.3 from gcc.godbolt.org also rejects the code. Clang 7.0.0 compiles it.

    – HolyBlackCat
    Mar 13 at 7:29
















Coliru uses GCC 8.2; GCC 8.3 from gcc.godbolt.org also rejects the code. Clang 7.0.0 compiles it.

– HolyBlackCat
Mar 13 at 7:29





Coliru uses GCC 8.2; GCC 8.3 from gcc.godbolt.org also rejects the code. Clang 7.0.0 compiles it.

– HolyBlackCat
Mar 13 at 7:29












2 Answers
2






active

oldest

votes


















14














Gcc is right. b (as constexpr variable) doesn't need to be captured in fact.




A lambda expression can read the value of a variable without capturing
it if the variable



  • is constexpr and has no mutable members.



GCC LIVE



It seems if making b static then MSVC could access b without capturing.



template<class T> void f()
constexpr static bool b=std::is_same_v<T,int>;
auto func_x=[]()
if constexpr(b)
else

;
func_x();



MSVC LIVE



And




How to work around it while keep the compile-time guarantee?




We can't keep the constexpr-ness for the captured variables. They become non-static data members of the lambda closure type and non-static data members can't be constexpr.






share|improve this answer

























  • Is there a location in the C++ standard where this is stated?

    – Nicol Bolas
    Mar 13 at 14:52











  • Indeed, C++17 seems to directly contradict this. b is implicitly captured by the lambda; there is no caveat about being a constant expression.

    – Nicol Bolas
    Mar 13 at 14:59







  • 3





    @NicolBolas since b is constexpr, performing an lvalue-to-rvalue conversion on it directly does not constitute an odr-use. See [basic.def.odr]/3 for the standard reference.

    – Brian
    Mar 13 at 15:14


















7















How to work around it while keep the compile-time guarantee?




Marking the constexpr bool as static serves as a work around.



See Demo



Alternately, you can use the condition in the if constexpr instead of assigning it to a bool. Like below:



if constexpr(std::is_same_v<T,int>)


See Demo



Note that there have been bugs raised for MSVC regarding constexpr with respect to lambda expressions.

One such is: problems with capturing constexpr in lambda

and another is: if constexpr in lambda






share|improve this answer
























    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%2f55136414%2fconstexpr-variable-captured-inside-lambda-loses-its-constexpr-ness%23new-answer', 'question_page');

    );

    Post as a guest















    Required, but never shown

























    2 Answers
    2






    active

    oldest

    votes








    2 Answers
    2






    active

    oldest

    votes









    active

    oldest

    votes






    active

    oldest

    votes









    14














    Gcc is right. b (as constexpr variable) doesn't need to be captured in fact.




    A lambda expression can read the value of a variable without capturing
    it if the variable



    • is constexpr and has no mutable members.



    GCC LIVE



    It seems if making b static then MSVC could access b without capturing.



    template<class T> void f()
    constexpr static bool b=std::is_same_v<T,int>;
    auto func_x=[]()
    if constexpr(b)
    else

    ;
    func_x();



    MSVC LIVE



    And




    How to work around it while keep the compile-time guarantee?




    We can't keep the constexpr-ness for the captured variables. They become non-static data members of the lambda closure type and non-static data members can't be constexpr.






    share|improve this answer

























    • Is there a location in the C++ standard where this is stated?

      – Nicol Bolas
      Mar 13 at 14:52











    • Indeed, C++17 seems to directly contradict this. b is implicitly captured by the lambda; there is no caveat about being a constant expression.

      – Nicol Bolas
      Mar 13 at 14:59







    • 3





      @NicolBolas since b is constexpr, performing an lvalue-to-rvalue conversion on it directly does not constitute an odr-use. See [basic.def.odr]/3 for the standard reference.

      – Brian
      Mar 13 at 15:14















    14














    Gcc is right. b (as constexpr variable) doesn't need to be captured in fact.




    A lambda expression can read the value of a variable without capturing
    it if the variable



    • is constexpr and has no mutable members.



    GCC LIVE



    It seems if making b static then MSVC could access b without capturing.



    template<class T> void f()
    constexpr static bool b=std::is_same_v<T,int>;
    auto func_x=[]()
    if constexpr(b)
    else

    ;
    func_x();



    MSVC LIVE



    And




    How to work around it while keep the compile-time guarantee?




    We can't keep the constexpr-ness for the captured variables. They become non-static data members of the lambda closure type and non-static data members can't be constexpr.






    share|improve this answer

























    • Is there a location in the C++ standard where this is stated?

      – Nicol Bolas
      Mar 13 at 14:52











    • Indeed, C++17 seems to directly contradict this. b is implicitly captured by the lambda; there is no caveat about being a constant expression.

      – Nicol Bolas
      Mar 13 at 14:59







    • 3





      @NicolBolas since b is constexpr, performing an lvalue-to-rvalue conversion on it directly does not constitute an odr-use. See [basic.def.odr]/3 for the standard reference.

      – Brian
      Mar 13 at 15:14













    14












    14








    14







    Gcc is right. b (as constexpr variable) doesn't need to be captured in fact.




    A lambda expression can read the value of a variable without capturing
    it if the variable



    • is constexpr and has no mutable members.



    GCC LIVE



    It seems if making b static then MSVC could access b without capturing.



    template<class T> void f()
    constexpr static bool b=std::is_same_v<T,int>;
    auto func_x=[]()
    if constexpr(b)
    else

    ;
    func_x();



    MSVC LIVE



    And




    How to work around it while keep the compile-time guarantee?




    We can't keep the constexpr-ness for the captured variables. They become non-static data members of the lambda closure type and non-static data members can't be constexpr.






    share|improve this answer















    Gcc is right. b (as constexpr variable) doesn't need to be captured in fact.




    A lambda expression can read the value of a variable without capturing
    it if the variable



    • is constexpr and has no mutable members.



    GCC LIVE



    It seems if making b static then MSVC could access b without capturing.



    template<class T> void f()
    constexpr static bool b=std::is_same_v<T,int>;
    auto func_x=[]()
    if constexpr(b)
    else

    ;
    func_x();



    MSVC LIVE



    And




    How to work around it while keep the compile-time guarantee?




    We can't keep the constexpr-ness for the captured variables. They become non-static data members of the lambda closure type and non-static data members can't be constexpr.







    share|improve this answer














    share|improve this answer



    share|improve this answer








    edited Mar 13 at 14:16

























    answered Mar 13 at 7:40









    songyuanyaosongyuanyao

    93.1k11181247




    93.1k11181247












    • Is there a location in the C++ standard where this is stated?

      – Nicol Bolas
      Mar 13 at 14:52











    • Indeed, C++17 seems to directly contradict this. b is implicitly captured by the lambda; there is no caveat about being a constant expression.

      – Nicol Bolas
      Mar 13 at 14:59







    • 3





      @NicolBolas since b is constexpr, performing an lvalue-to-rvalue conversion on it directly does not constitute an odr-use. See [basic.def.odr]/3 for the standard reference.

      – Brian
      Mar 13 at 15:14

















    • Is there a location in the C++ standard where this is stated?

      – Nicol Bolas
      Mar 13 at 14:52











    • Indeed, C++17 seems to directly contradict this. b is implicitly captured by the lambda; there is no caveat about being a constant expression.

      – Nicol Bolas
      Mar 13 at 14:59







    • 3





      @NicolBolas since b is constexpr, performing an lvalue-to-rvalue conversion on it directly does not constitute an odr-use. See [basic.def.odr]/3 for the standard reference.

      – Brian
      Mar 13 at 15:14
















    Is there a location in the C++ standard where this is stated?

    – Nicol Bolas
    Mar 13 at 14:52





    Is there a location in the C++ standard where this is stated?

    – Nicol Bolas
    Mar 13 at 14:52













    Indeed, C++17 seems to directly contradict this. b is implicitly captured by the lambda; there is no caveat about being a constant expression.

    – Nicol Bolas
    Mar 13 at 14:59






    Indeed, C++17 seems to directly contradict this. b is implicitly captured by the lambda; there is no caveat about being a constant expression.

    – Nicol Bolas
    Mar 13 at 14:59





    3




    3





    @NicolBolas since b is constexpr, performing an lvalue-to-rvalue conversion on it directly does not constitute an odr-use. See [basic.def.odr]/3 for the standard reference.

    – Brian
    Mar 13 at 15:14





    @NicolBolas since b is constexpr, performing an lvalue-to-rvalue conversion on it directly does not constitute an odr-use. See [basic.def.odr]/3 for the standard reference.

    – Brian
    Mar 13 at 15:14













    7















    How to work around it while keep the compile-time guarantee?




    Marking the constexpr bool as static serves as a work around.



    See Demo



    Alternately, you can use the condition in the if constexpr instead of assigning it to a bool. Like below:



    if constexpr(std::is_same_v<T,int>)


    See Demo



    Note that there have been bugs raised for MSVC regarding constexpr with respect to lambda expressions.

    One such is: problems with capturing constexpr in lambda

    and another is: if constexpr in lambda






    share|improve this answer





























      7















      How to work around it while keep the compile-time guarantee?




      Marking the constexpr bool as static serves as a work around.



      See Demo



      Alternately, you can use the condition in the if constexpr instead of assigning it to a bool. Like below:



      if constexpr(std::is_same_v<T,int>)


      See Demo



      Note that there have been bugs raised for MSVC regarding constexpr with respect to lambda expressions.

      One such is: problems with capturing constexpr in lambda

      and another is: if constexpr in lambda






      share|improve this answer



























        7












        7








        7








        How to work around it while keep the compile-time guarantee?




        Marking the constexpr bool as static serves as a work around.



        See Demo



        Alternately, you can use the condition in the if constexpr instead of assigning it to a bool. Like below:



        if constexpr(std::is_same_v<T,int>)


        See Demo



        Note that there have been bugs raised for MSVC regarding constexpr with respect to lambda expressions.

        One such is: problems with capturing constexpr in lambda

        and another is: if constexpr in lambda






        share|improve this answer
















        How to work around it while keep the compile-time guarantee?




        Marking the constexpr bool as static serves as a work around.



        See Demo



        Alternately, you can use the condition in the if constexpr instead of assigning it to a bool. Like below:



        if constexpr(std::is_same_v<T,int>)


        See Demo



        Note that there have been bugs raised for MSVC regarding constexpr with respect to lambda expressions.

        One such is: problems with capturing constexpr in lambda

        and another is: if constexpr in lambda







        share|improve this answer














        share|improve this answer



        share|improve this answer








        edited Mar 13 at 12:01

























        answered Mar 13 at 7:40









        P.WP.W

        16.8k41555




        16.8k41555



























            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%2f55136414%2fconstexpr-variable-captured-inside-lambda-loses-its-constexpr-ness%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

            Lowndes Grove History Architecture References Navigation menu32°48′6″N 79°57′58″W / 32.80167°N 79.96611°W / 32.80167; -79.9661132°48′6″N 79°57′58″W / 32.80167°N 79.96611°W / 32.80167; -79.9661178002500"National Register Information System"Historic houses of South Carolina"Lowndes Grove""+32° 48' 6.00", −79° 57' 58.00""Lowndes Grove, Charleston County (260 St. Margaret St., Charleston)""Lowndes Grove"The Charleston ExpositionIt Happened in South Carolina"Lowndes Grove (House), Saint Margaret Street & Sixth Avenue, Charleston, Charleston County, SC(Photographs)"Plantations of the Carolina Low Countrye

            random experiment with two different functions on unit interval Announcing the arrival of Valued Associate #679: Cesar Manara Planned maintenance scheduled April 23, 2019 at 00:00UTC (8:00pm US/Eastern)Random variable and probability space notionsRandom Walk with EdgesFinding functions where the increase over a random interval is Poisson distributedNumber of days until dayCan an observed event in fact be of zero probability?Unit random processmodels of coins and uniform distributionHow to get the number of successes given $n$ trials , probability $P$ and a random variable $X$Absorbing Markov chain in a computer. Is “almost every” turned into always convergence in computer executions?Stopped random walk is not uniformly integrable

            How should I support this large drywall patch? Planned maintenance scheduled April 23, 2019 at 00:00UTC (8:00pm US/Eastern) Announcing the arrival of Valued Associate #679: Cesar Manara Unicorn Meta Zoo #1: Why another podcast?How do I cover large gaps in drywall?How do I keep drywall around a patch from crumbling?Can I glue a second layer of drywall?How to patch long strip on drywall?Large drywall patch: how to avoid bulging seams?Drywall Mesh Patch vs. Bulge? To remove or not to remove?How to fix this drywall job?Prep drywall before backsplashWhat's the best way to fix this horrible drywall patch job?Drywall patching using 3M Patch Plus Primer