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

时间:2016-12-30 17:18:55

标签: c++ c++11 visual-studio-2015

是否可以验证传递给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功能。

1 个答案:

答案 0 :(得分:9)

虽然size()的{​​{1}}可以评估为std::initializer_list<T> constexpr成员在size()内的行为不会像constexpr } function:有意的是,对象在constexpr表达式中只表现为constexpr,而不是在其他地方。

例如:

constexpr

在第一种情况(1)中,假定产生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) // ... } 的值取决于constexpr开始之前创建的数据。因此,它不会评估为constexpr。在第二种情况(2)中,数据在constexpr内定义,因此结果可以变为constexpr

我没有参与导致这种设计的讨论,但似乎是因为希望阻止constexpr参数改变constexpr函数的结果类型:如果值是函数定义中的constexpr,它们在返回值中也可以是constexpr,因此可以在返回类型中用作模板参数。这会导致constexpr函数的值不同,从而产生不同的类型。到目前为止,只能通过改变函数的参数类型和/或通过改变函数的参数数量来获得不同的返回类型。