constexpr function with unused reference argument – gcc vs clang
.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty{ height:90px;width:728px;box-sizing:border-box;
}
Consider the following code:
template <int N, typename T> void f(T) { }
template <typename T>
constexpr int k(T&) { return 0; }
int main()
{
constexpr auto i = 1;
f<k(i)>([&i]
{
f<k(i)>(0);
});
}
clang++
(trunk) compiles it. g++
(trunk) fails with the following error:
<source>: In lambda function:
<source>:11:19: error: no matching function for call to 'f<k<const int>((* & i))>(int)'
11 | f<k(i)>(0);
| ^
<source>:1:35: note: candidate: 'template<int N, class T> void f(T)'
1 | template <int N, typename T> void f(T) { }
| ^
<source>:1:35: note: template argument deduction/substitution failed:
<source>:11:19: error: '__closure' is not a constant expression
11 | f<k(i)>(0);
| ^
<source>:11:13: note: in template argument for type 'int'
11 | f<k(i)>(0);
| ~^~~
live example on godbolt.org
Changing k(T&)
to k(T)
solves the issue. It seems to me that the problem is related to the fact that the reference argument is not a constant expression, but it not used as part of k
.
What compiler is correct here?
c++ templates language-lawyer c++17 constexpr
add a comment |
Consider the following code:
template <int N, typename T> void f(T) { }
template <typename T>
constexpr int k(T&) { return 0; }
int main()
{
constexpr auto i = 1;
f<k(i)>([&i]
{
f<k(i)>(0);
});
}
clang++
(trunk) compiles it. g++
(trunk) fails with the following error:
<source>: In lambda function:
<source>:11:19: error: no matching function for call to 'f<k<const int>((* & i))>(int)'
11 | f<k(i)>(0);
| ^
<source>:1:35: note: candidate: 'template<int N, class T> void f(T)'
1 | template <int N, typename T> void f(T) { }
| ^
<source>:1:35: note: template argument deduction/substitution failed:
<source>:11:19: error: '__closure' is not a constant expression
11 | f<k(i)>(0);
| ^
<source>:11:13: note: in template argument for type 'int'
11 | f<k(i)>(0);
| ~^~~
live example on godbolt.org
Changing k(T&)
to k(T)
solves the issue. It seems to me that the problem is related to the fact that the reference argument is not a constant expression, but it not used as part of k
.
What compiler is correct here?
c++ templates language-lawyer c++17 constexpr
2
Related: GCC and Clang disagree about C++17 constexpr lambda captures. T.C.'s answer also answers your question.
– xskxzr
Dec 30 '18 at 16:16
add a comment |
Consider the following code:
template <int N, typename T> void f(T) { }
template <typename T>
constexpr int k(T&) { return 0; }
int main()
{
constexpr auto i = 1;
f<k(i)>([&i]
{
f<k(i)>(0);
});
}
clang++
(trunk) compiles it. g++
(trunk) fails with the following error:
<source>: In lambda function:
<source>:11:19: error: no matching function for call to 'f<k<const int>((* & i))>(int)'
11 | f<k(i)>(0);
| ^
<source>:1:35: note: candidate: 'template<int N, class T> void f(T)'
1 | template <int N, typename T> void f(T) { }
| ^
<source>:1:35: note: template argument deduction/substitution failed:
<source>:11:19: error: '__closure' is not a constant expression
11 | f<k(i)>(0);
| ^
<source>:11:13: note: in template argument for type 'int'
11 | f<k(i)>(0);
| ~^~~
live example on godbolt.org
Changing k(T&)
to k(T)
solves the issue. It seems to me that the problem is related to the fact that the reference argument is not a constant expression, but it not used as part of k
.
What compiler is correct here?
c++ templates language-lawyer c++17 constexpr
Consider the following code:
template <int N, typename T> void f(T) { }
template <typename T>
constexpr int k(T&) { return 0; }
int main()
{
constexpr auto i = 1;
f<k(i)>([&i]
{
f<k(i)>(0);
});
}
clang++
(trunk) compiles it. g++
(trunk) fails with the following error:
<source>: In lambda function:
<source>:11:19: error: no matching function for call to 'f<k<const int>((* & i))>(int)'
11 | f<k(i)>(0);
| ^
<source>:1:35: note: candidate: 'template<int N, class T> void f(T)'
1 | template <int N, typename T> void f(T) { }
| ^
<source>:1:35: note: template argument deduction/substitution failed:
<source>:11:19: error: '__closure' is not a constant expression
11 | f<k(i)>(0);
| ^
<source>:11:13: note: in template argument for type 'int'
11 | f<k(i)>(0);
| ~^~~
live example on godbolt.org
Changing k(T&)
to k(T)
solves the issue. It seems to me that the problem is related to the fact that the reference argument is not a constant expression, but it not used as part of k
.
What compiler is correct here?
c++ templates language-lawyer c++17 constexpr
c++ templates language-lawyer c++17 constexpr
edited Dec 30 '18 at 13:40
Baum mit Augen♦
41.7k12120156
41.7k12120156
asked Dec 30 '18 at 13:29
Vittorio RomeoVittorio Romeo
60k17166310
60k17166310
2
Related: GCC and Clang disagree about C++17 constexpr lambda captures. T.C.'s answer also answers your question.
– xskxzr
Dec 30 '18 at 16:16
add a comment |
2
Related: GCC and Clang disagree about C++17 constexpr lambda captures. T.C.'s answer also answers your question.
– xskxzr
Dec 30 '18 at 16:16
2
2
Related: GCC and Clang disagree about C++17 constexpr lambda captures. T.C.'s answer also answers your question.
– xskxzr
Dec 30 '18 at 16:16
Related: GCC and Clang disagree about C++17 constexpr lambda captures. T.C.'s answer also answers your question.
– xskxzr
Dec 30 '18 at 16:16
add a comment |
3 Answers
3
active
oldest
votes
GCC is correct here.
According to [expr.const]/4:
An expression
e
is a core constant expression unless the evaluation
ofe
, following the rules of the abstract machine, would evaluate
one of the following expressions:
- ...
- in a lambda-expression, a reference to [...] a variable with automatic storage duration defined outside that lambda-expression,
where the reference would be an odr-use; ...
- ...
k(i)
odr-uses i
thus k(i)
is not a constant expression in the lambda expression, so this code is ill-formed.
add a comment |
The error is emitted for the expression k(i)
that appears within the lambda expression compound statements but not outside it. This is a GCC bug. According to [expr.prim.lambda.capture]/11
An id-expression within the compound-statement of a lambda-expression that is an odr-use of a reference captured by reference refers to the entity to which the captured reference is bound and not to the captured reference.
So k(i)
outside the lambda is the same expression as k(i)
outside the lambda, so there is no reason for GCC to emit an error for the second expression but not for the first.
add a comment |
Compiled with 0 errors on godbolt.
I used a variable result_k = k(i);
for bypass this errors.
template <int N, typename T> void f(T) { }
template <typename T> constexpr int k(T&) { return 0; }
int main() {
constexpr auto i = 1;
const int result_k=k(i);
f<result_k>([&i]{ f<result_k>(0);});
}
Rewrited code, the last code is not correct.
– Andreadjk
Dec 30 '18 at 15:48
3
This question is asking which compiler is correct, rather than how to resolve the issue.
– xskxzr
Dec 30 '18 at 16:26
clang++ (trunk) compiles it. g++ (trunk) fails with the following error: I posted the code beacause the owner use two compilers.. clang and g++, this code work with clag++ and g++
– Andreadjk
Dec 30 '18 at 17:41
2
And yes, that is a answer, but not the one the OP wants to know. This is question is taggedlanguage-laywer
and OP asks which compiler is correct, not how to fix it. An good answer would be telling OP whether clang or gcc is right, which yours does not do.
– Rakete1111
Dec 30 '18 at 20:37
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%2f53978006%2fconstexpr-function-with-unused-reference-argument-gcc-vs-clang%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
3 Answers
3
active
oldest
votes
3 Answers
3
active
oldest
votes
active
oldest
votes
active
oldest
votes
GCC is correct here.
According to [expr.const]/4:
An expression
e
is a core constant expression unless the evaluation
ofe
, following the rules of the abstract machine, would evaluate
one of the following expressions:
- ...
- in a lambda-expression, a reference to [...] a variable with automatic storage duration defined outside that lambda-expression,
where the reference would be an odr-use; ...
- ...
k(i)
odr-uses i
thus k(i)
is not a constant expression in the lambda expression, so this code is ill-formed.
add a comment |
GCC is correct here.
According to [expr.const]/4:
An expression
e
is a core constant expression unless the evaluation
ofe
, following the rules of the abstract machine, would evaluate
one of the following expressions:
- ...
- in a lambda-expression, a reference to [...] a variable with automatic storage duration defined outside that lambda-expression,
where the reference would be an odr-use; ...
- ...
k(i)
odr-uses i
thus k(i)
is not a constant expression in the lambda expression, so this code is ill-formed.
add a comment |
GCC is correct here.
According to [expr.const]/4:
An expression
e
is a core constant expression unless the evaluation
ofe
, following the rules of the abstract machine, would evaluate
one of the following expressions:
- ...
- in a lambda-expression, a reference to [...] a variable with automatic storage duration defined outside that lambda-expression,
where the reference would be an odr-use; ...
- ...
k(i)
odr-uses i
thus k(i)
is not a constant expression in the lambda expression, so this code is ill-formed.
GCC is correct here.
According to [expr.const]/4:
An expression
e
is a core constant expression unless the evaluation
ofe
, following the rules of the abstract machine, would evaluate
one of the following expressions:
- ...
- in a lambda-expression, a reference to [...] a variable with automatic storage duration defined outside that lambda-expression,
where the reference would be an odr-use; ...
- ...
k(i)
odr-uses i
thus k(i)
is not a constant expression in the lambda expression, so this code is ill-formed.
answered Dec 30 '18 at 16:23
xskxzrxskxzr
7,22992558
7,22992558
add a comment |
add a comment |
The error is emitted for the expression k(i)
that appears within the lambda expression compound statements but not outside it. This is a GCC bug. According to [expr.prim.lambda.capture]/11
An id-expression within the compound-statement of a lambda-expression that is an odr-use of a reference captured by reference refers to the entity to which the captured reference is bound and not to the captured reference.
So k(i)
outside the lambda is the same expression as k(i)
outside the lambda, so there is no reason for GCC to emit an error for the second expression but not for the first.
add a comment |
The error is emitted for the expression k(i)
that appears within the lambda expression compound statements but not outside it. This is a GCC bug. According to [expr.prim.lambda.capture]/11
An id-expression within the compound-statement of a lambda-expression that is an odr-use of a reference captured by reference refers to the entity to which the captured reference is bound and not to the captured reference.
So k(i)
outside the lambda is the same expression as k(i)
outside the lambda, so there is no reason for GCC to emit an error for the second expression but not for the first.
add a comment |
The error is emitted for the expression k(i)
that appears within the lambda expression compound statements but not outside it. This is a GCC bug. According to [expr.prim.lambda.capture]/11
An id-expression within the compound-statement of a lambda-expression that is an odr-use of a reference captured by reference refers to the entity to which the captured reference is bound and not to the captured reference.
So k(i)
outside the lambda is the same expression as k(i)
outside the lambda, so there is no reason for GCC to emit an error for the second expression but not for the first.
The error is emitted for the expression k(i)
that appears within the lambda expression compound statements but not outside it. This is a GCC bug. According to [expr.prim.lambda.capture]/11
An id-expression within the compound-statement of a lambda-expression that is an odr-use of a reference captured by reference refers to the entity to which the captured reference is bound and not to the captured reference.
So k(i)
outside the lambda is the same expression as k(i)
outside the lambda, so there is no reason for GCC to emit an error for the second expression but not for the first.
answered Dec 30 '18 at 14:33
OlivOliv
9,4271957
9,4271957
add a comment |
add a comment |
Compiled with 0 errors on godbolt.
I used a variable result_k = k(i);
for bypass this errors.
template <int N, typename T> void f(T) { }
template <typename T> constexpr int k(T&) { return 0; }
int main() {
constexpr auto i = 1;
const int result_k=k(i);
f<result_k>([&i]{ f<result_k>(0);});
}
Rewrited code, the last code is not correct.
– Andreadjk
Dec 30 '18 at 15:48
3
This question is asking which compiler is correct, rather than how to resolve the issue.
– xskxzr
Dec 30 '18 at 16:26
clang++ (trunk) compiles it. g++ (trunk) fails with the following error: I posted the code beacause the owner use two compilers.. clang and g++, this code work with clag++ and g++
– Andreadjk
Dec 30 '18 at 17:41
2
And yes, that is a answer, but not the one the OP wants to know. This is question is taggedlanguage-laywer
and OP asks which compiler is correct, not how to fix it. An good answer would be telling OP whether clang or gcc is right, which yours does not do.
– Rakete1111
Dec 30 '18 at 20:37
add a comment |
Compiled with 0 errors on godbolt.
I used a variable result_k = k(i);
for bypass this errors.
template <int N, typename T> void f(T) { }
template <typename T> constexpr int k(T&) { return 0; }
int main() {
constexpr auto i = 1;
const int result_k=k(i);
f<result_k>([&i]{ f<result_k>(0);});
}
Rewrited code, the last code is not correct.
– Andreadjk
Dec 30 '18 at 15:48
3
This question is asking which compiler is correct, rather than how to resolve the issue.
– xskxzr
Dec 30 '18 at 16:26
clang++ (trunk) compiles it. g++ (trunk) fails with the following error: I posted the code beacause the owner use two compilers.. clang and g++, this code work with clag++ and g++
– Andreadjk
Dec 30 '18 at 17:41
2
And yes, that is a answer, but not the one the OP wants to know. This is question is taggedlanguage-laywer
and OP asks which compiler is correct, not how to fix it. An good answer would be telling OP whether clang or gcc is right, which yours does not do.
– Rakete1111
Dec 30 '18 at 20:37
add a comment |
Compiled with 0 errors on godbolt.
I used a variable result_k = k(i);
for bypass this errors.
template <int N, typename T> void f(T) { }
template <typename T> constexpr int k(T&) { return 0; }
int main() {
constexpr auto i = 1;
const int result_k=k(i);
f<result_k>([&i]{ f<result_k>(0);});
}
Compiled with 0 errors on godbolt.
I used a variable result_k = k(i);
for bypass this errors.
template <int N, typename T> void f(T) { }
template <typename T> constexpr int k(T&) { return 0; }
int main() {
constexpr auto i = 1;
const int result_k=k(i);
f<result_k>([&i]{ f<result_k>(0);});
}
edited Dec 30 '18 at 16:26
xskxzr
7,22992558
7,22992558
answered Dec 30 '18 at 14:56
AndreadjkAndreadjk
11
11
Rewrited code, the last code is not correct.
– Andreadjk
Dec 30 '18 at 15:48
3
This question is asking which compiler is correct, rather than how to resolve the issue.
– xskxzr
Dec 30 '18 at 16:26
clang++ (trunk) compiles it. g++ (trunk) fails with the following error: I posted the code beacause the owner use two compilers.. clang and g++, this code work with clag++ and g++
– Andreadjk
Dec 30 '18 at 17:41
2
And yes, that is a answer, but not the one the OP wants to know. This is question is taggedlanguage-laywer
and OP asks which compiler is correct, not how to fix it. An good answer would be telling OP whether clang or gcc is right, which yours does not do.
– Rakete1111
Dec 30 '18 at 20:37
add a comment |
Rewrited code, the last code is not correct.
– Andreadjk
Dec 30 '18 at 15:48
3
This question is asking which compiler is correct, rather than how to resolve the issue.
– xskxzr
Dec 30 '18 at 16:26
clang++ (trunk) compiles it. g++ (trunk) fails with the following error: I posted the code beacause the owner use two compilers.. clang and g++, this code work with clag++ and g++
– Andreadjk
Dec 30 '18 at 17:41
2
And yes, that is a answer, but not the one the OP wants to know. This is question is taggedlanguage-laywer
and OP asks which compiler is correct, not how to fix it. An good answer would be telling OP whether clang or gcc is right, which yours does not do.
– Rakete1111
Dec 30 '18 at 20:37
Rewrited code, the last code is not correct.
– Andreadjk
Dec 30 '18 at 15:48
Rewrited code, the last code is not correct.
– Andreadjk
Dec 30 '18 at 15:48
3
3
This question is asking which compiler is correct, rather than how to resolve the issue.
– xskxzr
Dec 30 '18 at 16:26
This question is asking which compiler is correct, rather than how to resolve the issue.
– xskxzr
Dec 30 '18 at 16:26
clang++ (trunk) compiles it. g++ (trunk) fails with the following error: I posted the code beacause the owner use two compilers.. clang and g++, this code work with clag++ and g++
– Andreadjk
Dec 30 '18 at 17:41
clang++ (trunk) compiles it. g++ (trunk) fails with the following error: I posted the code beacause the owner use two compilers.. clang and g++, this code work with clag++ and g++
– Andreadjk
Dec 30 '18 at 17:41
2
2
And yes, that is a answer, but not the one the OP wants to know. This is question is tagged
language-laywer
and OP asks which compiler is correct, not how to fix it. An good answer would be telling OP whether clang or gcc is right, which yours does not do.– Rakete1111
Dec 30 '18 at 20:37
And yes, that is a answer, but not the one the OP wants to know. This is question is tagged
language-laywer
and OP asks which compiler is correct, not how to fix it. An good answer would be telling OP whether clang or gcc is right, which yours does not do.– Rakete1111
Dec 30 '18 at 20:37
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%2f53978006%2fconstexpr-function-with-unused-reference-argument-gcc-vs-clang%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
2
Related: GCC and Clang disagree about C++17 constexpr lambda captures. T.C.'s answer also answers your question.
– xskxzr
Dec 30 '18 at 16:16