std::is_constant_evaluated behavior












12















GCC9 already implements std::is_constant_evaluated. I played a little bit with it, and I realized it is somewhat tricky. Here’s my test:



constexpr int Fn1()
{
if constexpr (std::is_constant_evaluated())
return 0;
else
return 1;
}

constexpr int Fn2()
{
if (std::is_constant_evaluated())
return 0;
else
return 1;
}

int main()
{
constexpr int test1 = Fn1(); // Evaluates to 0
int test2 = Fn1(); // Evaluates to 0
int const test3 = Fn1(); // Evaluates to 0

constexpr int test4 = Fn2(); // Evaluates to 0
int test5 = Fn2(); // Evaluates to 1
int const test6 = Fn2(); // Evaluates to 0
}


According to these results, I extracted the following conclusions:




  • if constexpr (std::is_constant_evaluated()) always evaluates the
    true branch. Therefore, it makes no sense to use this construct.


  • If the compiler evaluates a variable at compile time,
    std::is_constant_evaluated()) is true, no matter whether that
    variable is explicitly annotated constexpr or not.



Am I right?










share|improve this question

























  • What headers and compiler options have you used for this?

    – P.W
    yesterday






  • 1





    @P.W the header <type_traits> and the compiler option -std=c++2a

    – metalfox
    yesterday


















12















GCC9 already implements std::is_constant_evaluated. I played a little bit with it, and I realized it is somewhat tricky. Here’s my test:



constexpr int Fn1()
{
if constexpr (std::is_constant_evaluated())
return 0;
else
return 1;
}

constexpr int Fn2()
{
if (std::is_constant_evaluated())
return 0;
else
return 1;
}

int main()
{
constexpr int test1 = Fn1(); // Evaluates to 0
int test2 = Fn1(); // Evaluates to 0
int const test3 = Fn1(); // Evaluates to 0

constexpr int test4 = Fn2(); // Evaluates to 0
int test5 = Fn2(); // Evaluates to 1
int const test6 = Fn2(); // Evaluates to 0
}


According to these results, I extracted the following conclusions:




  • if constexpr (std::is_constant_evaluated()) always evaluates the
    true branch. Therefore, it makes no sense to use this construct.


  • If the compiler evaluates a variable at compile time,
    std::is_constant_evaluated()) is true, no matter whether that
    variable is explicitly annotated constexpr or not.



Am I right?










share|improve this question

























  • What headers and compiler options have you used for this?

    – P.W
    yesterday






  • 1





    @P.W the header <type_traits> and the compiler option -std=c++2a

    – metalfox
    yesterday
















12












12








12


1






GCC9 already implements std::is_constant_evaluated. I played a little bit with it, and I realized it is somewhat tricky. Here’s my test:



constexpr int Fn1()
{
if constexpr (std::is_constant_evaluated())
return 0;
else
return 1;
}

constexpr int Fn2()
{
if (std::is_constant_evaluated())
return 0;
else
return 1;
}

int main()
{
constexpr int test1 = Fn1(); // Evaluates to 0
int test2 = Fn1(); // Evaluates to 0
int const test3 = Fn1(); // Evaluates to 0

constexpr int test4 = Fn2(); // Evaluates to 0
int test5 = Fn2(); // Evaluates to 1
int const test6 = Fn2(); // Evaluates to 0
}


According to these results, I extracted the following conclusions:




  • if constexpr (std::is_constant_evaluated()) always evaluates the
    true branch. Therefore, it makes no sense to use this construct.


  • If the compiler evaluates a variable at compile time,
    std::is_constant_evaluated()) is true, no matter whether that
    variable is explicitly annotated constexpr or not.



Am I right?










share|improve this question
















GCC9 already implements std::is_constant_evaluated. I played a little bit with it, and I realized it is somewhat tricky. Here’s my test:



constexpr int Fn1()
{
if constexpr (std::is_constant_evaluated())
return 0;
else
return 1;
}

constexpr int Fn2()
{
if (std::is_constant_evaluated())
return 0;
else
return 1;
}

int main()
{
constexpr int test1 = Fn1(); // Evaluates to 0
int test2 = Fn1(); // Evaluates to 0
int const test3 = Fn1(); // Evaluates to 0

constexpr int test4 = Fn2(); // Evaluates to 0
int test5 = Fn2(); // Evaluates to 1
int const test6 = Fn2(); // Evaluates to 0
}


According to these results, I extracted the following conclusions:




  • if constexpr (std::is_constant_evaluated()) always evaluates the
    true branch. Therefore, it makes no sense to use this construct.


  • If the compiler evaluates a variable at compile time,
    std::is_constant_evaluated()) is true, no matter whether that
    variable is explicitly annotated constexpr or not.



Am I right?







c++ constexpr c++20 if-constexpr






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited yesterday









Barry

179k19310570




179k19310570










asked yesterday









metalfoxmetalfox

1,792418




1,792418













  • What headers and compiler options have you used for this?

    – P.W
    yesterday






  • 1





    @P.W the header <type_traits> and the compiler option -std=c++2a

    – metalfox
    yesterday





















  • What headers and compiler options have you used for this?

    – P.W
    yesterday






  • 1





    @P.W the header <type_traits> and the compiler option -std=c++2a

    – metalfox
    yesterday



















What headers and compiler options have you used for this?

– P.W
yesterday





What headers and compiler options have you used for this?

– P.W
yesterday




1




1





@P.W the header <type_traits> and the compiler option -std=c++2a

– metalfox
yesterday







@P.W the header <type_traits> and the compiler option -std=c++2a

– metalfox
yesterday














2 Answers
2






active

oldest

votes


















10














if constexpr requires a constant expression for a condition. So is_constant_evaluated is of course always going to be true in such a context.



It's meant for a regular if. The purpose is to not go into a code path that is illegal in a constexpr function when evaluated in a constant expression. But to let it execute in runtime. It's not there to eliminate those code paths from the function altogether.






share|improve this answer


























  • there can be code paths in a constexpr function that cannot be evaluated at compile-time? There is so much I still have to learn :)

    – user463035818
    yesterday






  • 4





    @user463035818 constexpr means "there exist arguments to this function that may allow compile-time evaluation". It does not mean "this function will always be evaluated at compile-time". This means e.g. std::abs can be constexpr: When called with constexpr arguments it can be evaluated at compile-time, but it can still be used as normal at runtime.

    – Max Langhof
    yesterday











  • @MaxLanghof but can you actually implement a constexpr function with logic that can never be executed at compile time? I think that's what user463035818 meant. I am surprised too. The thing for function template is obvoisly different. Example which I think is relevant - you can never have a constexpr function that will return std::string, no matter where and how you'd call it.

    – Fureeish
    yesterday













  • @MaxLanghof ah thanks, got it. In case you pass non compile time arguments it makes little sense to require that the function can be evaluated at compile time

    – user463035818
    yesterday











  • I would have expected the compiler to optimize away the constant evaluation code path when generating the runtime version of the function, which is something likely to happen anyway. So if constexpr made sense to me.

    – metalfox
    yesterday



















4














Here's how I think about this, maybe you'll find this helpful... maybe not. Note that I think writing if constexpr (std::is_constant_evaluated()) will be a really common error, and it's an easy trap to fall into. But hopefully compilers will just diagnose that case.





We essentially have two different rules for code - the typical rules for normal runtime code, and the restrictions for constant expressions that are for constexpr programming. Those are the expr.const restrictions: no UB, no reinterpret_cast, etc. Those restrictions keep decreasing from language standard to language standard, which is great.



Basically, control flow (from a code path perspective) alternates between being in the "full runtime" mode and the constexpr mode. Once we enter the constexpr mode (whether by initializing a constexpr object or evaluating a template parameter or ...), we stay there until we're done... and then we're back to full runtime mode.



What is_constant_evaluated() does is simply: Am I in constexpr mode? It tells you if you're on a context that requires constant expressions.



In that view, let's look at if constexpr (is_constant_evaluated()). Regardless of what state we used to be in, if constexpr requires a constant expression as its initialized so this lifts us into constexpr mode if we weren't there already. Hence, is_constant_evaluated() is just true - unconditionally.



However, for if (is_constant_evaluated()), a simple if doesn't change our state between runtime and constexpr. So the value here depends on the context it was called from. Initializing test4 puts us onto constexpr mode because it's a constexpr object. For the duration of its initialization, we follow the constant expression rules... so is_constant_evaluated()is true. But once we're done, we're back to runtime rules... so in the initialization of test5, is_constant_evaluated() is false. (And then test6 is an unfortunate language special case - you can use constant integral variables as constant expressions, so we treat their initialization the same way for these purposes.)






share|improve this answer


























  • Thanks for the detailed explanation. I'm fine with the test6 case. It is quite logical to behave that way. I find the if constexpr case more counter-intuitive.

    – metalfox
    yesterday






  • 2





    @metalfox I suspect that will be a very common misunderstanding. I will add a note to the answer to that effect

    – Barry
    yesterday











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%2f54251530%2fstdis-constant-evaluated-behavior%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









10














if constexpr requires a constant expression for a condition. So is_constant_evaluated is of course always going to be true in such a context.



It's meant for a regular if. The purpose is to not go into a code path that is illegal in a constexpr function when evaluated in a constant expression. But to let it execute in runtime. It's not there to eliminate those code paths from the function altogether.






share|improve this answer


























  • there can be code paths in a constexpr function that cannot be evaluated at compile-time? There is so much I still have to learn :)

    – user463035818
    yesterday






  • 4





    @user463035818 constexpr means "there exist arguments to this function that may allow compile-time evaluation". It does not mean "this function will always be evaluated at compile-time". This means e.g. std::abs can be constexpr: When called with constexpr arguments it can be evaluated at compile-time, but it can still be used as normal at runtime.

    – Max Langhof
    yesterday











  • @MaxLanghof but can you actually implement a constexpr function with logic that can never be executed at compile time? I think that's what user463035818 meant. I am surprised too. The thing for function template is obvoisly different. Example which I think is relevant - you can never have a constexpr function that will return std::string, no matter where and how you'd call it.

    – Fureeish
    yesterday













  • @MaxLanghof ah thanks, got it. In case you pass non compile time arguments it makes little sense to require that the function can be evaluated at compile time

    – user463035818
    yesterday











  • I would have expected the compiler to optimize away the constant evaluation code path when generating the runtime version of the function, which is something likely to happen anyway. So if constexpr made sense to me.

    – metalfox
    yesterday
















10














if constexpr requires a constant expression for a condition. So is_constant_evaluated is of course always going to be true in such a context.



It's meant for a regular if. The purpose is to not go into a code path that is illegal in a constexpr function when evaluated in a constant expression. But to let it execute in runtime. It's not there to eliminate those code paths from the function altogether.






share|improve this answer


























  • there can be code paths in a constexpr function that cannot be evaluated at compile-time? There is so much I still have to learn :)

    – user463035818
    yesterday






  • 4





    @user463035818 constexpr means "there exist arguments to this function that may allow compile-time evaluation". It does not mean "this function will always be evaluated at compile-time". This means e.g. std::abs can be constexpr: When called with constexpr arguments it can be evaluated at compile-time, but it can still be used as normal at runtime.

    – Max Langhof
    yesterday











  • @MaxLanghof but can you actually implement a constexpr function with logic that can never be executed at compile time? I think that's what user463035818 meant. I am surprised too. The thing for function template is obvoisly different. Example which I think is relevant - you can never have a constexpr function that will return std::string, no matter where and how you'd call it.

    – Fureeish
    yesterday













  • @MaxLanghof ah thanks, got it. In case you pass non compile time arguments it makes little sense to require that the function can be evaluated at compile time

    – user463035818
    yesterday











  • I would have expected the compiler to optimize away the constant evaluation code path when generating the runtime version of the function, which is something likely to happen anyway. So if constexpr made sense to me.

    – metalfox
    yesterday














10












10








10







if constexpr requires a constant expression for a condition. So is_constant_evaluated is of course always going to be true in such a context.



It's meant for a regular if. The purpose is to not go into a code path that is illegal in a constexpr function when evaluated in a constant expression. But to let it execute in runtime. It's not there to eliminate those code paths from the function altogether.






share|improve this answer















if constexpr requires a constant expression for a condition. So is_constant_evaluated is of course always going to be true in such a context.



It's meant for a regular if. The purpose is to not go into a code path that is illegal in a constexpr function when evaluated in a constant expression. But to let it execute in runtime. It's not there to eliminate those code paths from the function altogether.







share|improve this answer














share|improve this answer



share|improve this answer








edited yesterday

























answered yesterday









StoryTellerStoryTeller

95.7k12195260




95.7k12195260













  • there can be code paths in a constexpr function that cannot be evaluated at compile-time? There is so much I still have to learn :)

    – user463035818
    yesterday






  • 4





    @user463035818 constexpr means "there exist arguments to this function that may allow compile-time evaluation". It does not mean "this function will always be evaluated at compile-time". This means e.g. std::abs can be constexpr: When called with constexpr arguments it can be evaluated at compile-time, but it can still be used as normal at runtime.

    – Max Langhof
    yesterday











  • @MaxLanghof but can you actually implement a constexpr function with logic that can never be executed at compile time? I think that's what user463035818 meant. I am surprised too. The thing for function template is obvoisly different. Example which I think is relevant - you can never have a constexpr function that will return std::string, no matter where and how you'd call it.

    – Fureeish
    yesterday













  • @MaxLanghof ah thanks, got it. In case you pass non compile time arguments it makes little sense to require that the function can be evaluated at compile time

    – user463035818
    yesterday











  • I would have expected the compiler to optimize away the constant evaluation code path when generating the runtime version of the function, which is something likely to happen anyway. So if constexpr made sense to me.

    – metalfox
    yesterday



















  • there can be code paths in a constexpr function that cannot be evaluated at compile-time? There is so much I still have to learn :)

    – user463035818
    yesterday






  • 4





    @user463035818 constexpr means "there exist arguments to this function that may allow compile-time evaluation". It does not mean "this function will always be evaluated at compile-time". This means e.g. std::abs can be constexpr: When called with constexpr arguments it can be evaluated at compile-time, but it can still be used as normal at runtime.

    – Max Langhof
    yesterday











  • @MaxLanghof but can you actually implement a constexpr function with logic that can never be executed at compile time? I think that's what user463035818 meant. I am surprised too. The thing for function template is obvoisly different. Example which I think is relevant - you can never have a constexpr function that will return std::string, no matter where and how you'd call it.

    – Fureeish
    yesterday













  • @MaxLanghof ah thanks, got it. In case you pass non compile time arguments it makes little sense to require that the function can be evaluated at compile time

    – user463035818
    yesterday











  • I would have expected the compiler to optimize away the constant evaluation code path when generating the runtime version of the function, which is something likely to happen anyway. So if constexpr made sense to me.

    – metalfox
    yesterday

















there can be code paths in a constexpr function that cannot be evaluated at compile-time? There is so much I still have to learn :)

– user463035818
yesterday





there can be code paths in a constexpr function that cannot be evaluated at compile-time? There is so much I still have to learn :)

– user463035818
yesterday




4




4





@user463035818 constexpr means "there exist arguments to this function that may allow compile-time evaluation". It does not mean "this function will always be evaluated at compile-time". This means e.g. std::abs can be constexpr: When called with constexpr arguments it can be evaluated at compile-time, but it can still be used as normal at runtime.

– Max Langhof
yesterday





@user463035818 constexpr means "there exist arguments to this function that may allow compile-time evaluation". It does not mean "this function will always be evaluated at compile-time". This means e.g. std::abs can be constexpr: When called with constexpr arguments it can be evaluated at compile-time, but it can still be used as normal at runtime.

– Max Langhof
yesterday













@MaxLanghof but can you actually implement a constexpr function with logic that can never be executed at compile time? I think that's what user463035818 meant. I am surprised too. The thing for function template is obvoisly different. Example which I think is relevant - you can never have a constexpr function that will return std::string, no matter where and how you'd call it.

– Fureeish
yesterday







@MaxLanghof but can you actually implement a constexpr function with logic that can never be executed at compile time? I think that's what user463035818 meant. I am surprised too. The thing for function template is obvoisly different. Example which I think is relevant - you can never have a constexpr function that will return std::string, no matter where and how you'd call it.

– Fureeish
yesterday















@MaxLanghof ah thanks, got it. In case you pass non compile time arguments it makes little sense to require that the function can be evaluated at compile time

– user463035818
yesterday





@MaxLanghof ah thanks, got it. In case you pass non compile time arguments it makes little sense to require that the function can be evaluated at compile time

– user463035818
yesterday













I would have expected the compiler to optimize away the constant evaluation code path when generating the runtime version of the function, which is something likely to happen anyway. So if constexpr made sense to me.

– metalfox
yesterday





I would have expected the compiler to optimize away the constant evaluation code path when generating the runtime version of the function, which is something likely to happen anyway. So if constexpr made sense to me.

– metalfox
yesterday













4














Here's how I think about this, maybe you'll find this helpful... maybe not. Note that I think writing if constexpr (std::is_constant_evaluated()) will be a really common error, and it's an easy trap to fall into. But hopefully compilers will just diagnose that case.





We essentially have two different rules for code - the typical rules for normal runtime code, and the restrictions for constant expressions that are for constexpr programming. Those are the expr.const restrictions: no UB, no reinterpret_cast, etc. Those restrictions keep decreasing from language standard to language standard, which is great.



Basically, control flow (from a code path perspective) alternates between being in the "full runtime" mode and the constexpr mode. Once we enter the constexpr mode (whether by initializing a constexpr object or evaluating a template parameter or ...), we stay there until we're done... and then we're back to full runtime mode.



What is_constant_evaluated() does is simply: Am I in constexpr mode? It tells you if you're on a context that requires constant expressions.



In that view, let's look at if constexpr (is_constant_evaluated()). Regardless of what state we used to be in, if constexpr requires a constant expression as its initialized so this lifts us into constexpr mode if we weren't there already. Hence, is_constant_evaluated() is just true - unconditionally.



However, for if (is_constant_evaluated()), a simple if doesn't change our state between runtime and constexpr. So the value here depends on the context it was called from. Initializing test4 puts us onto constexpr mode because it's a constexpr object. For the duration of its initialization, we follow the constant expression rules... so is_constant_evaluated()is true. But once we're done, we're back to runtime rules... so in the initialization of test5, is_constant_evaluated() is false. (And then test6 is an unfortunate language special case - you can use constant integral variables as constant expressions, so we treat their initialization the same way for these purposes.)






share|improve this answer


























  • Thanks for the detailed explanation. I'm fine with the test6 case. It is quite logical to behave that way. I find the if constexpr case more counter-intuitive.

    – metalfox
    yesterday






  • 2





    @metalfox I suspect that will be a very common misunderstanding. I will add a note to the answer to that effect

    – Barry
    yesterday
















4














Here's how I think about this, maybe you'll find this helpful... maybe not. Note that I think writing if constexpr (std::is_constant_evaluated()) will be a really common error, and it's an easy trap to fall into. But hopefully compilers will just diagnose that case.





We essentially have two different rules for code - the typical rules for normal runtime code, and the restrictions for constant expressions that are for constexpr programming. Those are the expr.const restrictions: no UB, no reinterpret_cast, etc. Those restrictions keep decreasing from language standard to language standard, which is great.



Basically, control flow (from a code path perspective) alternates between being in the "full runtime" mode and the constexpr mode. Once we enter the constexpr mode (whether by initializing a constexpr object or evaluating a template parameter or ...), we stay there until we're done... and then we're back to full runtime mode.



What is_constant_evaluated() does is simply: Am I in constexpr mode? It tells you if you're on a context that requires constant expressions.



In that view, let's look at if constexpr (is_constant_evaluated()). Regardless of what state we used to be in, if constexpr requires a constant expression as its initialized so this lifts us into constexpr mode if we weren't there already. Hence, is_constant_evaluated() is just true - unconditionally.



However, for if (is_constant_evaluated()), a simple if doesn't change our state between runtime and constexpr. So the value here depends on the context it was called from. Initializing test4 puts us onto constexpr mode because it's a constexpr object. For the duration of its initialization, we follow the constant expression rules... so is_constant_evaluated()is true. But once we're done, we're back to runtime rules... so in the initialization of test5, is_constant_evaluated() is false. (And then test6 is an unfortunate language special case - you can use constant integral variables as constant expressions, so we treat their initialization the same way for these purposes.)






share|improve this answer


























  • Thanks for the detailed explanation. I'm fine with the test6 case. It is quite logical to behave that way. I find the if constexpr case more counter-intuitive.

    – metalfox
    yesterday






  • 2





    @metalfox I suspect that will be a very common misunderstanding. I will add a note to the answer to that effect

    – Barry
    yesterday














4












4








4







Here's how I think about this, maybe you'll find this helpful... maybe not. Note that I think writing if constexpr (std::is_constant_evaluated()) will be a really common error, and it's an easy trap to fall into. But hopefully compilers will just diagnose that case.





We essentially have two different rules for code - the typical rules for normal runtime code, and the restrictions for constant expressions that are for constexpr programming. Those are the expr.const restrictions: no UB, no reinterpret_cast, etc. Those restrictions keep decreasing from language standard to language standard, which is great.



Basically, control flow (from a code path perspective) alternates between being in the "full runtime" mode and the constexpr mode. Once we enter the constexpr mode (whether by initializing a constexpr object or evaluating a template parameter or ...), we stay there until we're done... and then we're back to full runtime mode.



What is_constant_evaluated() does is simply: Am I in constexpr mode? It tells you if you're on a context that requires constant expressions.



In that view, let's look at if constexpr (is_constant_evaluated()). Regardless of what state we used to be in, if constexpr requires a constant expression as its initialized so this lifts us into constexpr mode if we weren't there already. Hence, is_constant_evaluated() is just true - unconditionally.



However, for if (is_constant_evaluated()), a simple if doesn't change our state between runtime and constexpr. So the value here depends on the context it was called from. Initializing test4 puts us onto constexpr mode because it's a constexpr object. For the duration of its initialization, we follow the constant expression rules... so is_constant_evaluated()is true. But once we're done, we're back to runtime rules... so in the initialization of test5, is_constant_evaluated() is false. (And then test6 is an unfortunate language special case - you can use constant integral variables as constant expressions, so we treat their initialization the same way for these purposes.)






share|improve this answer















Here's how I think about this, maybe you'll find this helpful... maybe not. Note that I think writing if constexpr (std::is_constant_evaluated()) will be a really common error, and it's an easy trap to fall into. But hopefully compilers will just diagnose that case.





We essentially have two different rules for code - the typical rules for normal runtime code, and the restrictions for constant expressions that are for constexpr programming. Those are the expr.const restrictions: no UB, no reinterpret_cast, etc. Those restrictions keep decreasing from language standard to language standard, which is great.



Basically, control flow (from a code path perspective) alternates between being in the "full runtime" mode and the constexpr mode. Once we enter the constexpr mode (whether by initializing a constexpr object or evaluating a template parameter or ...), we stay there until we're done... and then we're back to full runtime mode.



What is_constant_evaluated() does is simply: Am I in constexpr mode? It tells you if you're on a context that requires constant expressions.



In that view, let's look at if constexpr (is_constant_evaluated()). Regardless of what state we used to be in, if constexpr requires a constant expression as its initialized so this lifts us into constexpr mode if we weren't there already. Hence, is_constant_evaluated() is just true - unconditionally.



However, for if (is_constant_evaluated()), a simple if doesn't change our state between runtime and constexpr. So the value here depends on the context it was called from. Initializing test4 puts us onto constexpr mode because it's a constexpr object. For the duration of its initialization, we follow the constant expression rules... so is_constant_evaluated()is true. But once we're done, we're back to runtime rules... so in the initialization of test5, is_constant_evaluated() is false. (And then test6 is an unfortunate language special case - you can use constant integral variables as constant expressions, so we treat their initialization the same way for these purposes.)







share|improve this answer














share|improve this answer



share|improve this answer








edited yesterday

























answered yesterday









BarryBarry

179k19310570




179k19310570













  • Thanks for the detailed explanation. I'm fine with the test6 case. It is quite logical to behave that way. I find the if constexpr case more counter-intuitive.

    – metalfox
    yesterday






  • 2





    @metalfox I suspect that will be a very common misunderstanding. I will add a note to the answer to that effect

    – Barry
    yesterday



















  • Thanks for the detailed explanation. I'm fine with the test6 case. It is quite logical to behave that way. I find the if constexpr case more counter-intuitive.

    – metalfox
    yesterday






  • 2





    @metalfox I suspect that will be a very common misunderstanding. I will add a note to the answer to that effect

    – Barry
    yesterday

















Thanks for the detailed explanation. I'm fine with the test6 case. It is quite logical to behave that way. I find the if constexpr case more counter-intuitive.

– metalfox
yesterday





Thanks for the detailed explanation. I'm fine with the test6 case. It is quite logical to behave that way. I find the if constexpr case more counter-intuitive.

– metalfox
yesterday




2




2





@metalfox I suspect that will be a very common misunderstanding. I will add a note to the answer to that effect

– Barry
yesterday





@metalfox I suspect that will be a very common misunderstanding. I will add a note to the answer to that effect

– Barry
yesterday


















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%2f54251530%2fstdis-constant-evaluated-behavior%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

Callistus III

Plistias Cous

Index Sanctorum