约束将允许在函数参数上使用static_assert吗? [英] Will consteval allow using static_assert on function arguments?

查看:146
本文介绍了约束将允许在函数参数上使用static_assert吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

Currently you cannot use static_assert to verify parameters of a constexpr function, even if all calls to it are indeed constexpr. That makes sense because the compiler still has to create a non-constexpr instantiation of this function in case some other module will try to call it. Sadly, this is the case even if the function is static or in an anonymous namespace.

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

C++20 however, will introduce a new keyword consteval which is like constexpr but it doesn't allow calling a function in a non-constexpr way. In this case, the compiler can know for sure that the function parameters will always be known at compile time. Therefore, in theory it should be possible to validate them with 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;
}

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

I'm asking because I'm going to write some user-defined literals (more complicated than the example). I have an option to use compiler extensions to deal with the validation or wait a little for the compiler update and write fully standard-compliant code.

推荐答案

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

Will consteval allow to use static_assert on function arguments?

不.函数参数从未用作常量表达式,并且将继续不能用作常量表达式.

No. Function arguments have never been, and will continue to not be, usable as constant expressions.

被常量评估和可用作常量表达式之间存在差异. consteval确保我们处于恒定的评估上下文中,但不会同时使所有内容变为常数表达式.

There is a difference between something being constant evaluated and being usable as a constant-expression. consteval ensures that we're in a constant evaluation context, but it does not also cause everything to become constant-expressions.

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

In order to allow function arguments to be usable as constant expressions, you would need to make everything implicitly a template:

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
}

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

And now foo(20) and foo(30) return different types. That's a template.

有关理解为什么这是基本限制和内在限制的重要背景知识可以在安德鲁·萨顿(Andrew Sutton)的

Important background reading for understanding why this is a fundamental and inherent limitation can be found in Andrew Sutton's Translation and evaluation: A mental model for compile-time metaprogramming:

具有编译时评估的思维模型,可以将其与 翻译对我非常有帮助.特别是它帮助我了解了什么不是 可能的情况(例如,在评估过程中实例化模板).这有助于修剪以下内容的设计空间: 否则,语言功能会变得庞大而复杂.希望其他人也会对本说明有所帮助.

Having a mental model of compile-time evaluation that physically separates it from the process of translation has been extremely helpful for me. In particular, it has helped me understand what is not possible (e.g., instantiating a template during evaluation). This helps prune the design space for otherwise large and complex language features. Hopefully, others will find this note helpful as well.


不过,特别是使用static_assert时,您可以添加解决方法只是导致编译失败.那只是添加了在持续评估期间根本无法使用的所有内容.喜欢:


With static_assert specifically though, you can add a workaround just to cause a compilation failure. That's just adding anything at all that can't be used during constant evaluation. Like:

#define CONSTEVAL_STATIC_ASSERT(c, msg) do { if (!(c)) throw msg; } while(false)

如:

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

这篇关于约束将允许在函数参数上使用static_assert吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆