约束允许在函数参数上使用static_assert吗?

NO_*_*AME 9 c++ static-assert c++20 consteval

当前,即使对它的所有调用确实为,也无法用于static_assert验证constexpr函数的参数constexpr。这是有道理的,因为在某些其他模块尝试调用该函数的情况下,编译器仍必须为此函数创建一个非constexpr实例。可悲的是,即使函数是static或位于匿名名称空间中,也是如此。

然而,C ++ 20将引入一个新的关键字consteval,类似于constexpr但不允许以非constexpr的方式调用函数。在这种情况下,编译器可以确定在编译时始终知道函数参数。因此,从理论上讲,应该有可能使用进行验证static_assert

问题是:标准允许吗?


例:

#include <iostream>

consteval char operator""_bchar(const char text[], const size_t length)
{
    static_assert(length == 8, "Binary char has to have 8 digits!"); // <-- This is currently not possible.
    uint8_t byte = 0;
    for (size_t i = 0; i != length; ++i)
    {
        byte <<= 1;
        byte |= text[i] == '1' ? 0b00000001 : 0b00000000;
    }
    return byte;
}

int main()
{
    std::cout << "01000001"_bchar << std::endl;
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

我之所以问是因为我要编写一些用户定义的文字(比示例更复杂)。我可以选择使用编译器扩展来进行验证,或者稍等一下编译器更新并编写完全符合标准的代码。

Bar*_*rry 9

consteval允许在函数参数上使用static_assert吗?

不能。函数自变量从未用作常量表达式,并且以后将不再用作常量表达式。

常量被评估和可用作常量表达式之间是有区别的。consteval可以确保我们处于恒定的评估环境中,但不会同时使所有内容变为恒定的表达式。

为了使函数参数可用作常量表达式,您需要将所有内容隐式地做成模板:

template <int> struct X { };

consteval auto foo(int i) {
    static_assert(i > 10); // in order to allow this...
    return X<i>{};         // ... you'd have to allow this too
}
Run Code Online (Sandbox Code Playgroud)

现在foo(20)foo(30)返回不同的类型。那是一个模板。


可以在Andrew Sutton的《翻译和评估:编译时元编程的思维模型》中找到重要的背景知识,以了解为什么这是根本和固有的局限性:

拥有一种将编译时评估与翻译过程实际区分开来的编译时评估心理模型对我非常有帮助。特别是,它帮助我了解了不可能的事情(例如,在评估期间实例化模板)。这有助于为其他大型复杂语言功能修剪设计空间。希望其他人也会发现此注释对您有所帮助。


有了static_assert专门虽然,你可以再补充的解决方法,导致编译失败。这只是添加了在持续评估期间根本无法使用的所有内容。喜欢:

#define CONSTEVAL_STATIC_ASSERT(c, msg) do { if (!(c)) throw msg; } while(false)
Run Code Online (Sandbox Code Playgroud)

如:

consteval char operator""_bchar(const char text[], const size_t length)
{
    CONSTEVAL_STATIC_ASSERT(length == 8, "Binary char has to have 8 digits!");
    // ...
}
Run Code Online (Sandbox Code Playgroud)

  • “常量被评估与可用作常量表达式之间存在区别。”有什么区别? (3认同)
  • 嗯,我想保守函数已经需要在调用时显示其代码。那么隐式地使它们成为模板有什么问题呢? (2认同)