如何static_assert,初始化列表是一定大小

How to static_assert that an initializer list is a certain size

本文关键字:列表 初始化 static assert 如何      更新时间:2023-10-16

是否可以验证正在传递给constexpr构造函数的初始化列表是一定大小吗?还是只有在运行时才能做?

这是这个想法,但它不起作用:

struct group
{
        constexpr group(
            std::initializer_list<std::initializer_list<UINT const> const> groups
        )
        {
            static_assert(each_list_size_greater_than_1(groups.begin(), groups.end()));
        }
        constexpr static bool each_list_size_greater_than_1(
            std::initializer_list<std::initializer_list<UINT const> const>::const_iterator const begin
            , std::initializer_list<std::initializer_list<UINT const> const>::const_iterator const end)
        {
            return begin == end || begin->size() > 1 && each_list_size_greater_than_1(begin + 1, end);
        }
};

我已经查看了VS2015的std::initializer_list实现,begin()end()size()都是constexpr功能。

尽管std::initializer_list<T>size()可以评估constexpr size()成员在constexpr函数中不会像constexpr一样行为:这是故意的,只有对象像constexpr表达式中的constexpr一样行为他们被介绍的地方,但没有其他地方。

例如:

constexpr get_size(std::initializer_list<int> list) {
    constexpr std::size_t csize = list.size(); // ERROR (1)
    std::size_t           size  = list.size(); // OK
    return size;
}
int main() {
    constexpr std::size_t csize = get_size(std::initializer_list<int>{ 1, 2, 3 }); // OK (2)
    // ...
}

在第一种情况下(1)假定产生constexpr的值取决于constexpr启动之前创建的数据。结果,它没有评估constexpr。在第二种情况(2)中,数据是在constexpr中定义的,因此,结果可以成为constexpr

我还没有参与导致该设计的讨论的一部分,但是看来这是由于防止constexpr参数更改constexpr函数的结果类型的愿望而动机:如果值在功能定义中为constexpr s,则它们返回值也将是constexpr s,因此可以用作返回类型中的模板参数。这将导致constexpr功能产生不同类型的不同值。到目前为止,您只能通过更改函数的参数类型和/或通过更改函数的参数数量来获得其他返回类型。