问题:是否可以通过将其参数传递给内部constexpr函数(可能带有某种"完美转发")来评估函数内的常量表达式? 例如:
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!");
}
在documentation中找不到任何明确禁止的内容,但找不到解决方案,也不能证明不可能。 Constexpr的内在表达很重要。
答案 0 :(得分:7)
constexpr
函数的参数不能假定为constexpr
函数中的constexpr
;如果函数不是constexpr
,则该函数必须工作。
类型参数可以是。
如果您将bar("hello")
替换为bar( string_constant<'h', 'e', 'l', 'l', 'o'>{} )
template<char...>struct string_constant{};
,则字符的值现在会在该类型中进行编码,并且可以在路径下使用。还有其他方法可以将角色变成一种类型。
答案 1 :(得分:3)
不幸的是,这无法实现。 constexpr
函数的参数也不会自动constexpr
。毕竟可以从非constexpr
上下文调用该函数。您的编译器可能能够将您的案例优化为编译时评估,但这绝不是保证。
有一个常设解决方法是使用模板参数来强制某种constexpr
- 参数。您可以在this question中找到一个很好的例子。接下来,人们可能会想要这样做:
template<const char * string_literal> void baz() {
constexpr auto b = foo(string_literal);
}
int main() {
baz<"Definitely string literal too!">();
}
但是,这带来了非类型模板参数的限制,其中一个参数表示字符串文字不能是非类型模板参数。您可以使用Yakk建议的可变参数字符模板,如果可以应用于您的情况。
将来可能会添加对constexpr函数参数的支持。有关ISO C ++ Google网上论坛here的讨论。
如果确实需要完成工作,您还可以将baz转换为某种参数化宏。