constexpr function with unused reference argument – gcc vs clang
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
Related: GCC and Clang disagree about C++17 constexpr lambda captures. T.C.'s answer also answers your question.
– xskxzr
2 hours ago
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 4 hours ago
Baum mit Augen
40.2k12115147
40.2k12115147
asked 4 hours ago
Vittorio Romeo
57.3k17154293
57.3k17154293
Related: GCC and Clang disagree about C++17 constexpr lambda captures. T.C.'s answer also answers your question.
– xskxzr
2 hours ago
add a comment |
Related: GCC and Clang disagree about C++17 constexpr lambda captures. T.C.'s answer also answers your question.
– xskxzr
2 hours ago
Related: GCC and Clang disagree about C++17 constexpr lambda captures. T.C.'s answer also answers your question.
– xskxzr
2 hours ago
Related: GCC and Clang disagree about C++17 constexpr lambda captures. T.C.'s answer also answers your question.
– xskxzr
2 hours ago
add a comment |
4 Answers
4
active
oldest
votes
It's a GCC bug.
[expr.prim.lambda.capture]/13 - 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.
The expression inside the lambda that refer to k(i)
must be equivalent to
constexpr auto i = 1;
constexpr auto j = k(i);
which is accepted by both compilers. There are in fact some GCC reports similar to your example, two of them are GCC-86429 and GCC-82643
1
Where is the reference being captured?
– xskxzr
2 hours ago
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 |
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 |
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);});
}
New contributor
Rewrited code, the last code is not correct.
– Andreadjk
2 hours ago
1
This question is asking which compiler is correct, rather than how to resolve the issue.
– xskxzr
1 hour ago
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
41 mins ago
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
4 Answers
4
active
oldest
votes
4 Answers
4
active
oldest
votes
active
oldest
votes
active
oldest
votes
It's a GCC bug.
[expr.prim.lambda.capture]/13 - 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.
The expression inside the lambda that refer to k(i)
must be equivalent to
constexpr auto i = 1;
constexpr auto j = k(i);
which is accepted by both compilers. There are in fact some GCC reports similar to your example, two of them are GCC-86429 and GCC-82643
1
Where is the reference being captured?
– xskxzr
2 hours ago
add a comment |
It's a GCC bug.
[expr.prim.lambda.capture]/13 - 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.
The expression inside the lambda that refer to k(i)
must be equivalent to
constexpr auto i = 1;
constexpr auto j = k(i);
which is accepted by both compilers. There are in fact some GCC reports similar to your example, two of them are GCC-86429 and GCC-82643
1
Where is the reference being captured?
– xskxzr
2 hours ago
add a comment |
It's a GCC bug.
[expr.prim.lambda.capture]/13 - 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.
The expression inside the lambda that refer to k(i)
must be equivalent to
constexpr auto i = 1;
constexpr auto j = k(i);
which is accepted by both compilers. There are in fact some GCC reports similar to your example, two of them are GCC-86429 and GCC-82643
It's a GCC bug.
[expr.prim.lambda.capture]/13 - 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.
The expression inside the lambda that refer to k(i)
must be equivalent to
constexpr auto i = 1;
constexpr auto j = k(i);
which is accepted by both compilers. There are in fact some GCC reports similar to your example, two of them are GCC-86429 and GCC-82643
edited 3 hours ago
answered 3 hours ago
Jans
8,09522535
8,09522535
1
Where is the reference being captured?
– xskxzr
2 hours ago
add a comment |
1
Where is the reference being captured?
– xskxzr
2 hours ago
1
1
Where is the reference being captured?
– xskxzr
2 hours ago
Where is the reference being captured?
– xskxzr
2 hours ago
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 3 hours ago
Oliv
8,2501955
8,2501955
add a comment |
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.
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 1 hour ago
xskxzr
6,04082052
6,04082052
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);});
}
New contributor
Rewrited code, the last code is not correct.
– Andreadjk
2 hours ago
1
This question is asking which compiler is correct, rather than how to resolve the issue.
– xskxzr
1 hour ago
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
41 mins ago
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);});
}
New contributor
Rewrited code, the last code is not correct.
– Andreadjk
2 hours ago
1
This question is asking which compiler is correct, rather than how to resolve the issue.
– xskxzr
1 hour ago
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
41 mins ago
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);});
}
New contributor
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);});
}
New contributor
edited 1 hour ago
xskxzr
6,04082052
6,04082052
New contributor
answered 3 hours ago
Andreadjk
11
11
New contributor
New contributor
Rewrited code, the last code is not correct.
– Andreadjk
2 hours ago
1
This question is asking which compiler is correct, rather than how to resolve the issue.
– xskxzr
1 hour ago
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
41 mins ago
add a comment |
Rewrited code, the last code is not correct.
– Andreadjk
2 hours ago
1
This question is asking which compiler is correct, rather than how to resolve the issue.
– xskxzr
1 hour ago
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
41 mins ago
Rewrited code, the last code is not correct.
– Andreadjk
2 hours ago
Rewrited code, the last code is not correct.
– Andreadjk
2 hours ago
1
1
This question is asking which compiler is correct, rather than how to resolve the issue.
– xskxzr
1 hour ago
This question is asking which compiler is correct, rather than how to resolve the issue.
– xskxzr
1 hour ago
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
41 mins ago
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
41 mins ago
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.
Some of your past answers have not been well-received, and you're in danger of being blocked from answering.
Please pay close attention to the following guidance:
- 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
Related: GCC and Clang disagree about C++17 constexpr lambda captures. T.C.'s answer also answers your question.
– xskxzr
2 hours ago