本文介绍了std :: initializer_list :: size()与std :: array :: size()的constexpr-ness的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

限时删除!!

std :: initializer_list std :: array size()成员函数具有相同的签名:

The size() member functions of std::initializer_list and std::array have identical signatures:

constexpr size_type size() const noexcept;

都是 constexpr .但是,可以在 constexpr 上下文中使用 std :: array :: size(),但是可以使用 std :: initializer_list :: size()'t:

Both are constexpr. However, std::array::size() can be used in constexpr context, but std::initializer_list::size() can't:

std::initializer_list<int> il{1, 2, 3, 4};
constexpr std::size_t il_size = il.size();       // (1) - fails with GCC and Clang (*)

std::array<int, 4> arr{1, 2, 3, 4};
constexpr std::size_t arr_size = arr.size();     // (2) - OK

(*)错误是:

in 'constexpr' expansion of 'il.std::initializer_list<int>::size()'
error: the value of 'il' is not usable in a constant expression

据我了解,(1)失败而(2)成功的事实是完全合理,因为类模板的 constexpr 成员函数可能无法满足 constexpr 的要求.

As far as I understand, the fact that (1) fails and (2) succeeds is perfectly reasonable because constexpr member function of a class template may fail to satisfy constexpr requirements.

我有两个相关的问题:

  1. 为什么 std :: initializer_list 不能以(1)编译的方式实现?标准中是否有阻止这种实现的措施?
  2. 鉴于(1)失败,将 std :: initializer_list :: size()标记为 constexpr 的目的是什么>?唯一的用例似乎就是这个:

  1. Why isn't std::initializer_list implemented in a way such that (1) compiles? Is there something in the standard that prevents such an implementation?
  2. Given that (1) fails, what is the purpose of marking std::initializer_list::size() as constexpr? The only use case seems to be this one:

constexpr std::initializer_list<int> il{1, 2, 3, 4};   // note constexpr
constexpr std::size_t il_size = il.size();

推荐答案

是的,这是不可能的. initializer_list 可以具有任何大小,您不能在恒定的评估时间内获得任意运行时 initializer_list 的大小.这与 std :: array 完全不同,在给定的 std :: array< T,N> 中,大小为 N .一个人的大小是可变的,另一个人的大小是固定的.

Yes, it's impossible. An initializer_list can have any size, you cannot during constant evaluation time get the size of an arbitrary runtime initializer_list. This is quite different from std::array, where a given std::array<T, N> has size N. One's size is variable, the other's is fixed.

这与其他任何变量都没有真正的区别:

This isn't really different from any other variable:

struct X { int i; };

X x{42};
constexpr X cx{17};

constexpr int i = x.i;   // error
constexpr int ci = cx.i; // ok

这不是唯一的用例,远非如此. constexpr 成员函数不仅允许您在 constexpr 对象上调用它们.通常,它们使您可以在持续评估时间内在任意位置调用它们.

This is not the only use case, far from. constexpr member functions do not just permit you to invoke them on constexpr objects. They more generally permit you to invoke them anywhere during constant evaluation time.

也就是说,在进行任何形式的持续评估时,如果创建 initializer_list ,则可以使用其大小.一个愚蠢的最小示例可能是:

That is, during any kind of constant evaluation, if you create an initializer_list, you can then use its size. A silly minimal example might be:

constexpr size_t four() {
    std::initializer_list<int> lst = {1, 2, 3, 4};
    return lst.size();
}

static_assert(four() == 4);

请注意, lst 本身不是 constexpr 对象,它只是在评估对 four()的调用的过程中创建的一些短暂的东西./code>进行持续评估.但是我们仍然需要 size() constexpr -调用任何非 constexpr 函数是不行的.

Note that lst itself is not a constexpr object, it's just some ephemeral thing that got created during the course of evaluating the call to four() during constant evaluation. But we still need that size() to be constexpr - invoking any non-constexpr function is a no-no.

您可以从此处将其向外扩展到任意要运行的任意代码,在持续评估过程中要确定 std :: initializer_list 的大小.

From here you can extend it outwards to any arbitrary code you might want to run that at some point, during constant evaluation, wants to determine the size of an std::initializer_list.

这篇关于std :: initializer_list :: size()与std :: array :: size()的constexpr-ness的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

1403页,肝出来的..

09-06 09:21