The question: is it possible to evaluate constant expression inside a function by passing (maybe with some kind of "perfect forwarding") its argument to inner constexpr function? Example:
constexpr size_t foo(char const* string_literal) {
return /*some valid recursive black magic*/;
}
void bar(char const* string_literal) {
// works fine
constexpr auto a = foo("Definitely string literal.");
// compile error: "string_literal" is not a constant expression
constexpr auto b = foo(string_literal);
}
template<typename T>
void baz(T&& string_literal) {
// doesn't compile as well with the same error
constexpr auto b = foo(std::forward<T>(string_literal));
}
int main() {
// gonna do this, wont compile due to errors mentioned above
bar("Definitely string literal too!");
}
Can't find anything clearly prohibiting in the documentation, but the solution isn't found, as well as a proof of impossibility. Constexpr'ness of inner expression is important.
Parameters to constexpr
functions cannot be assumed to be constexpr
within a constexpr
function; the function must work if they are not constexpr
.
Type parameters can be.
If you replaced bar("hello")
with bar( string_constant<'h', 'e', 'l', 'l', 'o'>{} )
with template<char...>struct string_constant{};
, the value of the characters is now encoded in the type and will be available down the path. There are other ways to get the characters into a type.
Unfortunately, this cannot be achieved. Parameters to a constexpr
function are not automatically constexpr
as well. The function can after all be called from non-constexpr
context. Your compiler might be able to optimize your case into compile-time evaluation, but this is in no way guaranteed.
There is a standing workaround to use template parameters to force a kind of constexpr
-ness to a parameter. You can find a good example in this question. Following on that, one might be tempted to do this:
template<const char * string_literal> void baz() {
constexpr auto b = foo(string_literal);
}
int main() {
baz<"Definitely string literal too!">();
}
However, this comes with the limitations on non-type template parameters, one of which says that a string literal cannot be a non-type template parameter. You can use the variadic char template, as suggested by Yakk, if that can be applied to your case.
The support for constexpr function parameters might be added in the future. There is a discussion on ISO C++ Google Groups here.
You can also convert baz into some kind of parameterized macro, if you really need the job done.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With