C++ constexpr function in return statement
Why is a constexpr function no evaluated at compile time but in runtime in the return statement of main function?
It tried
template<int x>
constexpr int fac() {
return fac<x - 1>() * x;
}
template<>
constexpr int fac<1>() {
return 1;
}
int main() {
const int x = fac<3>();
return x;
}
and the result is
main:
push rbp
mov rbp, rsp
mov DWORD PTR [rbp-4], 6
mov eax, 6
pop rbp
ret
with gcc 8.2. But when I call the function in the return statement
template<int x>
constexpr int fac() {
return fac<x - 1>() * x;
}
template<>
constexpr int fac<1>() {
return 1;
}
int main() {
return fac<3>();
}
I get
int fac<1>():
push rbp
mov rbp, rsp
mov eax, 1
pop rbp
ret
main:
push rbp
mov rbp, rsp
call int fac<3>()
nop
pop rbp
ret
int fac<2>():
push rbp
mov rbp, rsp
call int fac<1>()
add eax, eax
pop rbp
ret
int fac<3>():
push rbp
mov rbp, rsp
call int fac<2>()
mov edx, eax
mov eax, edx
add eax, eax
add eax, edx
pop rbp
ret
Why is the first code evaluated at compile time and the second at runtime?
Also I tried both snippets with clang 7.0.0 and they are evaluated at runtime. Why is this not valid constexpr for clang?
All evaluation was done in godbolt compiler explorer.
c++ gcc clang constexpr
|
show 5 more comments
Why is a constexpr function no evaluated at compile time but in runtime in the return statement of main function?
It tried
template<int x>
constexpr int fac() {
return fac<x - 1>() * x;
}
template<>
constexpr int fac<1>() {
return 1;
}
int main() {
const int x = fac<3>();
return x;
}
and the result is
main:
push rbp
mov rbp, rsp
mov DWORD PTR [rbp-4], 6
mov eax, 6
pop rbp
ret
with gcc 8.2. But when I call the function in the return statement
template<int x>
constexpr int fac() {
return fac<x - 1>() * x;
}
template<>
constexpr int fac<1>() {
return 1;
}
int main() {
return fac<3>();
}
I get
int fac<1>():
push rbp
mov rbp, rsp
mov eax, 1
pop rbp
ret
main:
push rbp
mov rbp, rsp
call int fac<3>()
nop
pop rbp
ret
int fac<2>():
push rbp
mov rbp, rsp
call int fac<1>()
add eax, eax
pop rbp
ret
int fac<3>():
push rbp
mov rbp, rsp
call int fac<2>()
mov edx, eax
mov eax, edx
add eax, eax
add eax, edx
pop rbp
ret
Why is the first code evaluated at compile time and the second at runtime?
Also I tried both snippets with clang 7.0.0 and they are evaluated at runtime. Why is this not valid constexpr for clang?
All evaluation was done in godbolt compiler explorer.
c++ gcc clang constexpr
15
You should use-O3
for optimal behaviour, the question is meaningless without it. As posted the question is really about "why does the compiler without optimization do this thing" to which the answer is usually "to make debugging easier"
– M.M
Jan 14 at 12:47
5
And both compilers in question do exactly what you would expect with optimizations enabled: godbolt.org/z/cCbFDX
– Max Langhof
Jan 14 at 12:49
15
constexpr
exists to let you write natural code for producing constant expressions in contexts that need them. It's not a "optimize this to heck always" hint to the compiler. It's best not to confuse it for one.
– StoryTeller
Jan 14 at 12:51
2
@StoryTeller that comment helped me more than thousands books. I think you should make it an answer. I always thoughtconstexpr
is to tell the compiler "this should be evaluated at compile time", while I now understand that it is rather "this must be evaluatable at compile time". Suddenly the confusion about whether it does get evaluated at compile time or not feels much less severe.
– user463035818
Jan 14 at 13:02
1
It's worth mentioning that in this particular example there is no need to passx
as a template parameter. An "ordinary" parameter will suffice here. So, you can useconstexpr
functions as a more readable replacement for some old style meta-programming-template-code that previously had to be used to generate compile time integers.
– sebrockm
Jan 14 at 16:01
|
show 5 more comments
Why is a constexpr function no evaluated at compile time but in runtime in the return statement of main function?
It tried
template<int x>
constexpr int fac() {
return fac<x - 1>() * x;
}
template<>
constexpr int fac<1>() {
return 1;
}
int main() {
const int x = fac<3>();
return x;
}
and the result is
main:
push rbp
mov rbp, rsp
mov DWORD PTR [rbp-4], 6
mov eax, 6
pop rbp
ret
with gcc 8.2. But when I call the function in the return statement
template<int x>
constexpr int fac() {
return fac<x - 1>() * x;
}
template<>
constexpr int fac<1>() {
return 1;
}
int main() {
return fac<3>();
}
I get
int fac<1>():
push rbp
mov rbp, rsp
mov eax, 1
pop rbp
ret
main:
push rbp
mov rbp, rsp
call int fac<3>()
nop
pop rbp
ret
int fac<2>():
push rbp
mov rbp, rsp
call int fac<1>()
add eax, eax
pop rbp
ret
int fac<3>():
push rbp
mov rbp, rsp
call int fac<2>()
mov edx, eax
mov eax, edx
add eax, eax
add eax, edx
pop rbp
ret
Why is the first code evaluated at compile time and the second at runtime?
Also I tried both snippets with clang 7.0.0 and they are evaluated at runtime. Why is this not valid constexpr for clang?
All evaluation was done in godbolt compiler explorer.
c++ gcc clang constexpr
Why is a constexpr function no evaluated at compile time but in runtime in the return statement of main function?
It tried
template<int x>
constexpr int fac() {
return fac<x - 1>() * x;
}
template<>
constexpr int fac<1>() {
return 1;
}
int main() {
const int x = fac<3>();
return x;
}
and the result is
main:
push rbp
mov rbp, rsp
mov DWORD PTR [rbp-4], 6
mov eax, 6
pop rbp
ret
with gcc 8.2. But when I call the function in the return statement
template<int x>
constexpr int fac() {
return fac<x - 1>() * x;
}
template<>
constexpr int fac<1>() {
return 1;
}
int main() {
return fac<3>();
}
I get
int fac<1>():
push rbp
mov rbp, rsp
mov eax, 1
pop rbp
ret
main:
push rbp
mov rbp, rsp
call int fac<3>()
nop
pop rbp
ret
int fac<2>():
push rbp
mov rbp, rsp
call int fac<1>()
add eax, eax
pop rbp
ret
int fac<3>():
push rbp
mov rbp, rsp
call int fac<2>()
mov edx, eax
mov eax, edx
add eax, eax
add eax, edx
pop rbp
ret
Why is the first code evaluated at compile time and the second at runtime?
Also I tried both snippets with clang 7.0.0 and they are evaluated at runtime. Why is this not valid constexpr for clang?
All evaluation was done in godbolt compiler explorer.
c++ gcc clang constexpr
c++ gcc clang constexpr
edited Jan 14 at 13:51
Thomas Sablik
asked Jan 14 at 12:43
Thomas SablikThomas Sablik
2,62811129
2,62811129
15
You should use-O3
for optimal behaviour, the question is meaningless without it. As posted the question is really about "why does the compiler without optimization do this thing" to which the answer is usually "to make debugging easier"
– M.M
Jan 14 at 12:47
5
And both compilers in question do exactly what you would expect with optimizations enabled: godbolt.org/z/cCbFDX
– Max Langhof
Jan 14 at 12:49
15
constexpr
exists to let you write natural code for producing constant expressions in contexts that need them. It's not a "optimize this to heck always" hint to the compiler. It's best not to confuse it for one.
– StoryTeller
Jan 14 at 12:51
2
@StoryTeller that comment helped me more than thousands books. I think you should make it an answer. I always thoughtconstexpr
is to tell the compiler "this should be evaluated at compile time", while I now understand that it is rather "this must be evaluatable at compile time". Suddenly the confusion about whether it does get evaluated at compile time or not feels much less severe.
– user463035818
Jan 14 at 13:02
1
It's worth mentioning that in this particular example there is no need to passx
as a template parameter. An "ordinary" parameter will suffice here. So, you can useconstexpr
functions as a more readable replacement for some old style meta-programming-template-code that previously had to be used to generate compile time integers.
– sebrockm
Jan 14 at 16:01
|
show 5 more comments
15
You should use-O3
for optimal behaviour, the question is meaningless without it. As posted the question is really about "why does the compiler without optimization do this thing" to which the answer is usually "to make debugging easier"
– M.M
Jan 14 at 12:47
5
And both compilers in question do exactly what you would expect with optimizations enabled: godbolt.org/z/cCbFDX
– Max Langhof
Jan 14 at 12:49
15
constexpr
exists to let you write natural code for producing constant expressions in contexts that need them. It's not a "optimize this to heck always" hint to the compiler. It's best not to confuse it for one.
– StoryTeller
Jan 14 at 12:51
2
@StoryTeller that comment helped me more than thousands books. I think you should make it an answer. I always thoughtconstexpr
is to tell the compiler "this should be evaluated at compile time", while I now understand that it is rather "this must be evaluatable at compile time". Suddenly the confusion about whether it does get evaluated at compile time or not feels much less severe.
– user463035818
Jan 14 at 13:02
1
It's worth mentioning that in this particular example there is no need to passx
as a template parameter. An "ordinary" parameter will suffice here. So, you can useconstexpr
functions as a more readable replacement for some old style meta-programming-template-code that previously had to be used to generate compile time integers.
– sebrockm
Jan 14 at 16:01
15
15
You should use
-O3
for optimal behaviour, the question is meaningless without it. As posted the question is really about "why does the compiler without optimization do this thing" to which the answer is usually "to make debugging easier"– M.M
Jan 14 at 12:47
You should use
-O3
for optimal behaviour, the question is meaningless without it. As posted the question is really about "why does the compiler without optimization do this thing" to which the answer is usually "to make debugging easier"– M.M
Jan 14 at 12:47
5
5
And both compilers in question do exactly what you would expect with optimizations enabled: godbolt.org/z/cCbFDX
– Max Langhof
Jan 14 at 12:49
And both compilers in question do exactly what you would expect with optimizations enabled: godbolt.org/z/cCbFDX
– Max Langhof
Jan 14 at 12:49
15
15
constexpr
exists to let you write natural code for producing constant expressions in contexts that need them. It's not a "optimize this to heck always" hint to the compiler. It's best not to confuse it for one.– StoryTeller
Jan 14 at 12:51
constexpr
exists to let you write natural code for producing constant expressions in contexts that need them. It's not a "optimize this to heck always" hint to the compiler. It's best not to confuse it for one.– StoryTeller
Jan 14 at 12:51
2
2
@StoryTeller that comment helped me more than thousands books. I think you should make it an answer. I always thought
constexpr
is to tell the compiler "this should be evaluated at compile time", while I now understand that it is rather "this must be evaluatable at compile time". Suddenly the confusion about whether it does get evaluated at compile time or not feels much less severe.– user463035818
Jan 14 at 13:02
@StoryTeller that comment helped me more than thousands books. I think you should make it an answer. I always thought
constexpr
is to tell the compiler "this should be evaluated at compile time", while I now understand that it is rather "this must be evaluatable at compile time". Suddenly the confusion about whether it does get evaluated at compile time or not feels much less severe.– user463035818
Jan 14 at 13:02
1
1
It's worth mentioning that in this particular example there is no need to pass
x
as a template parameter. An "ordinary" parameter will suffice here. So, you can use constexpr
functions as a more readable replacement for some old style meta-programming-template-code that previously had to be used to generate compile time integers.– sebrockm
Jan 14 at 16:01
It's worth mentioning that in this particular example there is no need to pass
x
as a template parameter. An "ordinary" parameter will suffice here. So, you can use constexpr
functions as a more readable replacement for some old style meta-programming-template-code that previously had to be used to generate compile time integers.– sebrockm
Jan 14 at 16:01
|
show 5 more comments
2 Answers
2
active
oldest
votes
A common misconception with regard to constexpr
is that it means "this will be evaluated at compile time"1.
It is not. constexpr
was introduced to let us write natural code that may produce constant expressions in contexts that need them. It means "this must be evaluatable at compile time", which is what the compiler will check.
So if you wrote a constexpr
function returning an int, you can use it to calculate a template argument, an initializer for a constexpr
variable (also const
if it's an integral type) or an array size. You can use the function to obtain natural, declarative, readable code instead of the old meta-programming tricks one needed to resort to in the past.
But a constexpr
function is still a regular function. The constexpr
specifier doesn't mean a compiler has2 to optimize it to heck and do constant folding at compile time. It's best not to confuse it for such a hint.
1 - Thanks user463035818 for the phrasing.
2 - c++20 and consteval
is a different story however :)
Actually, it means "This must be evaluatable at compile time for at least one input (arguments and template-arguments).", which is weaker still. Yes, that should hold for any useful input, but expectations are often disappointed.
– Deduplicator
Jan 14 at 20:54
Do you know whyconstexpr
is even necessary? Why can't the compiler just assume everything hasconstexpr
in front of it?
– Mehrdad
Jan 14 at 22:05
@Mehrdad - It's by no means authoritative, just my 2c. The standard prohibits certain constructs in constexpr functions, less so now than in C++11, but still. I guess for ease translation, and for keeping programmers sane, it's better to make it an opt-in feature. Which is kinda also inline with the general philosophy of C++.
– StoryTeller
Jan 15 at 7:07
add a comment |
StoryTeller's answer is good, but I think there's a slightly different take possible.
With constexpr
, there are three situations to distinguish:
The result is needed in a compile-time context, such as array sizes. In this case, the arguments too must be known at compile time. Evaluation is probably at compile time, and at least all diagnosable errors will be found at compile time.
The arguments are only known at run time, and the result is not needed at compile time. In this case, evaluation necessarily has to happen at run time.
The arguments may be available at compile time, but the result is needed only at run time.
The fourth combination (arguments available only at runtime, result needed at compile time) is an error; the compiler will reject such code.
Now in cases 1 and 3 the calculation could happen at compile time, as all inputs are available. But to facilitate case 2, the compiler must be able to create a run-time version, and it may decide to use this variant in the other cases as well - if it can.
E.g. some compilers internally support variable-sized arrays, so even while the language requires compile-time array bounds, the implementation may decide not to.
Shouldn't case 2 lead to a compilation error instead? Theconstexpr
indicates that the expression must be evaluable at compile time.
– fishinear
Jan 14 at 18:03
1
@fishinear No. The answer is referring to a the uses of aconstexpr
function. E.g. if I haveconstexpr int factorial(int n)
, and I have anint input
I only know at runtime,int output = factorial(input);
is perfectly fine. The error would be claimingconstexpr int output = factorial(input);
, becauseinput
is notconstexpr
, so neither canoutput
beconstexpr
.
– HTNW
Jan 14 at 18:32
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%2f54181797%2fc-constexpr-function-in-return-statement%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
A common misconception with regard to constexpr
is that it means "this will be evaluated at compile time"1.
It is not. constexpr
was introduced to let us write natural code that may produce constant expressions in contexts that need them. It means "this must be evaluatable at compile time", which is what the compiler will check.
So if you wrote a constexpr
function returning an int, you can use it to calculate a template argument, an initializer for a constexpr
variable (also const
if it's an integral type) or an array size. You can use the function to obtain natural, declarative, readable code instead of the old meta-programming tricks one needed to resort to in the past.
But a constexpr
function is still a regular function. The constexpr
specifier doesn't mean a compiler has2 to optimize it to heck and do constant folding at compile time. It's best not to confuse it for such a hint.
1 - Thanks user463035818 for the phrasing.
2 - c++20 and consteval
is a different story however :)
Actually, it means "This must be evaluatable at compile time for at least one input (arguments and template-arguments).", which is weaker still. Yes, that should hold for any useful input, but expectations are often disappointed.
– Deduplicator
Jan 14 at 20:54
Do you know whyconstexpr
is even necessary? Why can't the compiler just assume everything hasconstexpr
in front of it?
– Mehrdad
Jan 14 at 22:05
@Mehrdad - It's by no means authoritative, just my 2c. The standard prohibits certain constructs in constexpr functions, less so now than in C++11, but still. I guess for ease translation, and for keeping programmers sane, it's better to make it an opt-in feature. Which is kinda also inline with the general philosophy of C++.
– StoryTeller
Jan 15 at 7:07
add a comment |
A common misconception with regard to constexpr
is that it means "this will be evaluated at compile time"1.
It is not. constexpr
was introduced to let us write natural code that may produce constant expressions in contexts that need them. It means "this must be evaluatable at compile time", which is what the compiler will check.
So if you wrote a constexpr
function returning an int, you can use it to calculate a template argument, an initializer for a constexpr
variable (also const
if it's an integral type) or an array size. You can use the function to obtain natural, declarative, readable code instead of the old meta-programming tricks one needed to resort to in the past.
But a constexpr
function is still a regular function. The constexpr
specifier doesn't mean a compiler has2 to optimize it to heck and do constant folding at compile time. It's best not to confuse it for such a hint.
1 - Thanks user463035818 for the phrasing.
2 - c++20 and consteval
is a different story however :)
Actually, it means "This must be evaluatable at compile time for at least one input (arguments and template-arguments).", which is weaker still. Yes, that should hold for any useful input, but expectations are often disappointed.
– Deduplicator
Jan 14 at 20:54
Do you know whyconstexpr
is even necessary? Why can't the compiler just assume everything hasconstexpr
in front of it?
– Mehrdad
Jan 14 at 22:05
@Mehrdad - It's by no means authoritative, just my 2c. The standard prohibits certain constructs in constexpr functions, less so now than in C++11, but still. I guess for ease translation, and for keeping programmers sane, it's better to make it an opt-in feature. Which is kinda also inline with the general philosophy of C++.
– StoryTeller
Jan 15 at 7:07
add a comment |
A common misconception with regard to constexpr
is that it means "this will be evaluated at compile time"1.
It is not. constexpr
was introduced to let us write natural code that may produce constant expressions in contexts that need them. It means "this must be evaluatable at compile time", which is what the compiler will check.
So if you wrote a constexpr
function returning an int, you can use it to calculate a template argument, an initializer for a constexpr
variable (also const
if it's an integral type) or an array size. You can use the function to obtain natural, declarative, readable code instead of the old meta-programming tricks one needed to resort to in the past.
But a constexpr
function is still a regular function. The constexpr
specifier doesn't mean a compiler has2 to optimize it to heck and do constant folding at compile time. It's best not to confuse it for such a hint.
1 - Thanks user463035818 for the phrasing.
2 - c++20 and consteval
is a different story however :)
A common misconception with regard to constexpr
is that it means "this will be evaluated at compile time"1.
It is not. constexpr
was introduced to let us write natural code that may produce constant expressions in contexts that need them. It means "this must be evaluatable at compile time", which is what the compiler will check.
So if you wrote a constexpr
function returning an int, you can use it to calculate a template argument, an initializer for a constexpr
variable (also const
if it's an integral type) or an array size. You can use the function to obtain natural, declarative, readable code instead of the old meta-programming tricks one needed to resort to in the past.
But a constexpr
function is still a regular function. The constexpr
specifier doesn't mean a compiler has2 to optimize it to heck and do constant folding at compile time. It's best not to confuse it for such a hint.
1 - Thanks user463035818 for the phrasing.
2 - c++20 and consteval
is a different story however :)
edited Jan 14 at 13:39
answered Jan 14 at 13:08
StoryTellerStoryTeller
97.5k12199265
97.5k12199265
Actually, it means "This must be evaluatable at compile time for at least one input (arguments and template-arguments).", which is weaker still. Yes, that should hold for any useful input, but expectations are often disappointed.
– Deduplicator
Jan 14 at 20:54
Do you know whyconstexpr
is even necessary? Why can't the compiler just assume everything hasconstexpr
in front of it?
– Mehrdad
Jan 14 at 22:05
@Mehrdad - It's by no means authoritative, just my 2c. The standard prohibits certain constructs in constexpr functions, less so now than in C++11, but still. I guess for ease translation, and for keeping programmers sane, it's better to make it an opt-in feature. Which is kinda also inline with the general philosophy of C++.
– StoryTeller
Jan 15 at 7:07
add a comment |
Actually, it means "This must be evaluatable at compile time for at least one input (arguments and template-arguments).", which is weaker still. Yes, that should hold for any useful input, but expectations are often disappointed.
– Deduplicator
Jan 14 at 20:54
Do you know whyconstexpr
is even necessary? Why can't the compiler just assume everything hasconstexpr
in front of it?
– Mehrdad
Jan 14 at 22:05
@Mehrdad - It's by no means authoritative, just my 2c. The standard prohibits certain constructs in constexpr functions, less so now than in C++11, but still. I guess for ease translation, and for keeping programmers sane, it's better to make it an opt-in feature. Which is kinda also inline with the general philosophy of C++.
– StoryTeller
Jan 15 at 7:07
Actually, it means "This must be evaluatable at compile time for at least one input (arguments and template-arguments).", which is weaker still. Yes, that should hold for any useful input, but expectations are often disappointed.
– Deduplicator
Jan 14 at 20:54
Actually, it means "This must be evaluatable at compile time for at least one input (arguments and template-arguments).", which is weaker still. Yes, that should hold for any useful input, but expectations are often disappointed.
– Deduplicator
Jan 14 at 20:54
Do you know why
constexpr
is even necessary? Why can't the compiler just assume everything has constexpr
in front of it?– Mehrdad
Jan 14 at 22:05
Do you know why
constexpr
is even necessary? Why can't the compiler just assume everything has constexpr
in front of it?– Mehrdad
Jan 14 at 22:05
@Mehrdad - It's by no means authoritative, just my 2c. The standard prohibits certain constructs in constexpr functions, less so now than in C++11, but still. I guess for ease translation, and for keeping programmers sane, it's better to make it an opt-in feature. Which is kinda also inline with the general philosophy of C++.
– StoryTeller
Jan 15 at 7:07
@Mehrdad - It's by no means authoritative, just my 2c. The standard prohibits certain constructs in constexpr functions, less so now than in C++11, but still. I guess for ease translation, and for keeping programmers sane, it's better to make it an opt-in feature. Which is kinda also inline with the general philosophy of C++.
– StoryTeller
Jan 15 at 7:07
add a comment |
StoryTeller's answer is good, but I think there's a slightly different take possible.
With constexpr
, there are three situations to distinguish:
The result is needed in a compile-time context, such as array sizes. In this case, the arguments too must be known at compile time. Evaluation is probably at compile time, and at least all diagnosable errors will be found at compile time.
The arguments are only known at run time, and the result is not needed at compile time. In this case, evaluation necessarily has to happen at run time.
The arguments may be available at compile time, but the result is needed only at run time.
The fourth combination (arguments available only at runtime, result needed at compile time) is an error; the compiler will reject such code.
Now in cases 1 and 3 the calculation could happen at compile time, as all inputs are available. But to facilitate case 2, the compiler must be able to create a run-time version, and it may decide to use this variant in the other cases as well - if it can.
E.g. some compilers internally support variable-sized arrays, so even while the language requires compile-time array bounds, the implementation may decide not to.
Shouldn't case 2 lead to a compilation error instead? Theconstexpr
indicates that the expression must be evaluable at compile time.
– fishinear
Jan 14 at 18:03
1
@fishinear No. The answer is referring to a the uses of aconstexpr
function. E.g. if I haveconstexpr int factorial(int n)
, and I have anint input
I only know at runtime,int output = factorial(input);
is perfectly fine. The error would be claimingconstexpr int output = factorial(input);
, becauseinput
is notconstexpr
, so neither canoutput
beconstexpr
.
– HTNW
Jan 14 at 18:32
add a comment |
StoryTeller's answer is good, but I think there's a slightly different take possible.
With constexpr
, there are three situations to distinguish:
The result is needed in a compile-time context, such as array sizes. In this case, the arguments too must be known at compile time. Evaluation is probably at compile time, and at least all diagnosable errors will be found at compile time.
The arguments are only known at run time, and the result is not needed at compile time. In this case, evaluation necessarily has to happen at run time.
The arguments may be available at compile time, but the result is needed only at run time.
The fourth combination (arguments available only at runtime, result needed at compile time) is an error; the compiler will reject such code.
Now in cases 1 and 3 the calculation could happen at compile time, as all inputs are available. But to facilitate case 2, the compiler must be able to create a run-time version, and it may decide to use this variant in the other cases as well - if it can.
E.g. some compilers internally support variable-sized arrays, so even while the language requires compile-time array bounds, the implementation may decide not to.
Shouldn't case 2 lead to a compilation error instead? Theconstexpr
indicates that the expression must be evaluable at compile time.
– fishinear
Jan 14 at 18:03
1
@fishinear No. The answer is referring to a the uses of aconstexpr
function. E.g. if I haveconstexpr int factorial(int n)
, and I have anint input
I only know at runtime,int output = factorial(input);
is perfectly fine. The error would be claimingconstexpr int output = factorial(input);
, becauseinput
is notconstexpr
, so neither canoutput
beconstexpr
.
– HTNW
Jan 14 at 18:32
add a comment |
StoryTeller's answer is good, but I think there's a slightly different take possible.
With constexpr
, there are three situations to distinguish:
The result is needed in a compile-time context, such as array sizes. In this case, the arguments too must be known at compile time. Evaluation is probably at compile time, and at least all diagnosable errors will be found at compile time.
The arguments are only known at run time, and the result is not needed at compile time. In this case, evaluation necessarily has to happen at run time.
The arguments may be available at compile time, but the result is needed only at run time.
The fourth combination (arguments available only at runtime, result needed at compile time) is an error; the compiler will reject such code.
Now in cases 1 and 3 the calculation could happen at compile time, as all inputs are available. But to facilitate case 2, the compiler must be able to create a run-time version, and it may decide to use this variant in the other cases as well - if it can.
E.g. some compilers internally support variable-sized arrays, so even while the language requires compile-time array bounds, the implementation may decide not to.
StoryTeller's answer is good, but I think there's a slightly different take possible.
With constexpr
, there are three situations to distinguish:
The result is needed in a compile-time context, such as array sizes. In this case, the arguments too must be known at compile time. Evaluation is probably at compile time, and at least all diagnosable errors will be found at compile time.
The arguments are only known at run time, and the result is not needed at compile time. In this case, evaluation necessarily has to happen at run time.
The arguments may be available at compile time, but the result is needed only at run time.
The fourth combination (arguments available only at runtime, result needed at compile time) is an error; the compiler will reject such code.
Now in cases 1 and 3 the calculation could happen at compile time, as all inputs are available. But to facilitate case 2, the compiler must be able to create a run-time version, and it may decide to use this variant in the other cases as well - if it can.
E.g. some compilers internally support variable-sized arrays, so even while the language requires compile-time array bounds, the implementation may decide not to.
answered Jan 14 at 13:42
MSaltersMSalters
134k8117270
134k8117270
Shouldn't case 2 lead to a compilation error instead? Theconstexpr
indicates that the expression must be evaluable at compile time.
– fishinear
Jan 14 at 18:03
1
@fishinear No. The answer is referring to a the uses of aconstexpr
function. E.g. if I haveconstexpr int factorial(int n)
, and I have anint input
I only know at runtime,int output = factorial(input);
is perfectly fine. The error would be claimingconstexpr int output = factorial(input);
, becauseinput
is notconstexpr
, so neither canoutput
beconstexpr
.
– HTNW
Jan 14 at 18:32
add a comment |
Shouldn't case 2 lead to a compilation error instead? Theconstexpr
indicates that the expression must be evaluable at compile time.
– fishinear
Jan 14 at 18:03
1
@fishinear No. The answer is referring to a the uses of aconstexpr
function. E.g. if I haveconstexpr int factorial(int n)
, and I have anint input
I only know at runtime,int output = factorial(input);
is perfectly fine. The error would be claimingconstexpr int output = factorial(input);
, becauseinput
is notconstexpr
, so neither canoutput
beconstexpr
.
– HTNW
Jan 14 at 18:32
Shouldn't case 2 lead to a compilation error instead? The
constexpr
indicates that the expression must be evaluable at compile time.– fishinear
Jan 14 at 18:03
Shouldn't case 2 lead to a compilation error instead? The
constexpr
indicates that the expression must be evaluable at compile time.– fishinear
Jan 14 at 18:03
1
1
@fishinear No. The answer is referring to a the uses of a
constexpr
function. E.g. if I have constexpr int factorial(int n)
, and I have an int input
I only know at runtime, int output = factorial(input);
is perfectly fine. The error would be claiming constexpr int output = factorial(input);
, because input
is not constexpr
, so neither can output
be constexpr
.– HTNW
Jan 14 at 18:32
@fishinear No. The answer is referring to a the uses of a
constexpr
function. E.g. if I have constexpr int factorial(int n)
, and I have an int input
I only know at runtime, int output = factorial(input);
is perfectly fine. The error would be claiming constexpr int output = factorial(input);
, because input
is not constexpr
, so neither can output
be constexpr
.– HTNW
Jan 14 at 18:32
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%2f54181797%2fc-constexpr-function-in-return-statement%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
15
You should use
-O3
for optimal behaviour, the question is meaningless without it. As posted the question is really about "why does the compiler without optimization do this thing" to which the answer is usually "to make debugging easier"– M.M
Jan 14 at 12:47
5
And both compilers in question do exactly what you would expect with optimizations enabled: godbolt.org/z/cCbFDX
– Max Langhof
Jan 14 at 12:49
15
constexpr
exists to let you write natural code for producing constant expressions in contexts that need them. It's not a "optimize this to heck always" hint to the compiler. It's best not to confuse it for one.– StoryTeller
Jan 14 at 12:51
2
@StoryTeller that comment helped me more than thousands books. I think you should make it an answer. I always thought
constexpr
is to tell the compiler "this should be evaluated at compile time", while I now understand that it is rather "this must be evaluatable at compile time". Suddenly the confusion about whether it does get evaluated at compile time or not feels much less severe.– user463035818
Jan 14 at 13:02
1
It's worth mentioning that in this particular example there is no need to pass
x
as a template parameter. An "ordinary" parameter will suffice here. So, you can useconstexpr
functions as a more readable replacement for some old style meta-programming-template-code that previously had to be used to generate compile time integers.– sebrockm
Jan 14 at 16:01