Constexpr variable captured inside lambda loses its constexpr-ness
Clash Royale CLAN TAG#URR8PPP
.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty height:90px;width:728px;box-sizing:border-box;
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
add a comment |
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
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
add a comment |
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
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
c++ lambda language-lawyer c++17 if-constexpr
edited Mar 13 at 7:30
HolyBlackCat
17.2k33568
17.2k33568
asked Mar 13 at 7:21
javaLoverjavaLover
2,7741939
2,7741939
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
add a comment |
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
add a comment |
2 Answers
2
active
oldest
votes
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
.
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 sinceb
isconstexpr
, 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
add a comment |
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
add a comment |
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
);
);
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
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
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
.
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 sinceb
isconstexpr
, 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
add a comment |
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
.
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 sinceb
isconstexpr
, 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
add a comment |
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
.
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
.
edited Mar 13 at 14:16
answered Mar 13 at 7:40
songyuanyaosongyuanyao
94.1k11182250
94.1k11182250
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 sinceb
isconstexpr
, 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
add a comment |
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 sinceb
isconstexpr
, 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
add a comment |
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
add a comment |
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
add a comment |
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
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
edited Mar 13 at 12:01
answered Mar 13 at 7:40
P.WP.W
18.6k41758
18.6k41758
add a comment |
add a comment |
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.
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
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
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
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
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