【问题标题】:Is there a way to forward argument to inner constexpr function?有没有办法将参数转发给内部 constexpr 函数?
【发布时间】:2017-01-07 06:02:11
【问题描述】:

问题:是否可以通过将(可能使用某种“完美转发”)其参数传递给内部 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 中找不到任何明确禁止的内容,但没有找到解决方案,以及不可能的证明。内在表达的约束性很重要。

【问题讨论】:

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


【解决方案1】:

constexpr 函数的参数不能假定为 constexpr 函数中的 constexpr;如果不是constexpr,该函数必须工作

类型参数即可。

如果您将bar("hello") 替换为bar( string_constant&lt;'h', 'e', 'l', 'l', 'o'&gt;{} )template&lt;char...&gt;struct string_constant{};,则字符的值现在在类型中进行编码,并且将在路径中可用。还有其他方法可以将字符转换为类型。

【讨论】:

    【解决方案2】:

    很遗憾,这无法实现。 constexpr 函数的参数也不会自动为 constexpr。毕竟可以从非constexpr 上下文中调用该函数。您的编译器可能能够将您的案例优化为编译时评估,但这绝不能保证。

    有一个常用的解决方法是使用模板参数来强制参数使用constexpr-ness。你可以在this question 中找到一个很好的例子。紧接着,人们可能会想这样做:

    template<const char * string_literal> void baz() {
        constexpr auto b = foo(string_literal); 
    }
    
    int main() {
        baz<"Definitely string literal too!">(); 
    }
    

    然而,这伴随着对非类型模板参数的限制,其中之一是说字符串文字不能是非类型模板参数。如果可以将其应用于您的案例,您可以使用 Yakk 建议的 variadic char 模板。

    将来可能会添加对 constexpr 函数参数的支持。有一个关于 ISO C++ Google Groups here的讨论。

    如果您真的需要完成这项工作,您还可以将 baz 转换为某种参数化宏。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2022-01-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-09-27
      • 1970-01-01
      • 2020-04-15
      相关资源
      最近更新 更多