Constexpr variable captured inside lambda loses its constexpr-ness
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
19 hours ago
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 19 hours ago
HolyBlackCat
16.8k33468
16.8k33468
asked 19 hours ago
javaLoverjavaLover
2,7821939
2,7821939
Coliru uses GCC 8.2; GCC 8.3 from gcc.godbolt.org also rejects the code. Clang 7.0.0 compiles it.
– HolyBlackCat
19 hours ago
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
19 hours ago
Coliru uses GCC 8.2; GCC 8.3 from gcc.godbolt.org also rejects the code. Clang 7.0.0 compiles it.
– HolyBlackCat
19 hours ago
Coliru uses GCC 8.2; GCC 8.3 from gcc.godbolt.org also rejects the code. Clang 7.0.0 compiles it.
– HolyBlackCat
19 hours ago
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
12 hours ago
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
12 hours ago
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
11 hours ago
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
12 hours ago
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
12 hours ago
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
11 hours ago
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
12 hours ago
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
12 hours ago
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
11 hours ago
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 12 hours ago
answered 19 hours ago
songyuanyaosongyuanyao
92.9k11178244
92.9k11178244
Is there a location in the C++ standard where this is stated?
– Nicol Bolas
12 hours ago
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
12 hours ago
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
11 hours ago
add a comment |
Is there a location in the C++ standard where this is stated?
– Nicol Bolas
12 hours ago
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
12 hours ago
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
11 hours ago
Is there a location in the C++ standard where this is stated?
– Nicol Bolas
12 hours ago
Is there a location in the C++ standard where this is stated?
– Nicol Bolas
12 hours ago
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
12 hours ago
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
12 hours ago
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
11 hours ago
@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
11 hours ago
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 15 hours ago
answered 19 hours ago
P.WP.W
16.4k31455
16.4k31455
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
19 hours ago