有没有办法将参数转发给内部constexpr函数?

时间:2016-08-30 20:03:30

标签: c++ c++11 constexpr perfect-forwarding

问题:是否可以通过将其参数传递给内部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的内在表达很重要。

2 个答案:

答案 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转换为某种参数化宏。