为什么`std :: initializer_list`没有提供下标运算符?

voi*_*ter 35 c++ iterator operator-overloading initializer-list c++11

假设您正在编写一个接受被std::initializer_list调用list的函数,并且该函数需要随机访问其list元素.写list[i]代替是方便的list.begin()[i].那么为什么不std::initializer_list提供定义operator[]呢?

我想不出任何operator[]返回const T&不明确的情况.效率在这里似乎不是问题,因为std::initializer_list<T>::iterator别名const T*,显然是随机访问迭代器.

Hom*_*er6 11

根据Bjarne Stroustrup在C++编程语言第17版第17.3.4.2节(第497页)中的说法:

不幸的是,initializer_list不提供下标.

没有进一步的理由.

我的猜测是,这是以下原因之一:

  1. 这是一个遗漏,或者
  2. 因为initializer_list类是用数组实现的,你必须进行边界检查以提供安全访问,如果提供了该接口,它可能更容易被不安全地使用,或者
  3. 与std算法迭代范式一致,或者
  4. 因为initializer_lists本质上是ad-hoc,所以通过直接解决它们会有更多的错误空间

2和4听起来有点弱.我的钱是1.

  • @jippyjoe4 现在9岁了!:) (3认同)
  • 6年后,我们知道答案了吗? (2认同)

Ami*_*rsh 7

这确实有点烦人,没有 std::initializer_list 的方括号运算符,因为需要随机直接访问特定索引是一个合理的场景。

但是,可以通过一些简单的代码添加此功能:

// the class _init_list_with_square_brackets provides [] for initializer_list
template<class T>
struct _init_list_with_square_brackets {
    const std::initializer_list<T>& list;
    _init_list_with_square_brackets(const std::initializer_list<T>& _list): list(_list) {}
    T operator[](unsigned int index) {
        return *(list.begin() + index);
    } 
};

// a function, with the short name _ (underscore) for creating 
// the _init_list_with_square_brackets out of a "regular" std::initializer_list
template<class T>
_init_list_with_square_brackets<T> _(const std::initializer_list<T>& list) {
    return _init_list_with_square_brackets<T>(list);
}
Run Code Online (Sandbox Code Playgroud)

现在我们有了一个名为 _(下划线)的新全局函数,它对于全局 C++ 方法来说可能不是一个好名字,除非我们想为 C++ 创建一些“类似 undescore”的实用程序库,它有自己的命名空间,重载_ 函数用于各种其他有用的用法。

现在可以像这样使用新的 _ 函数:

void f(std::initializer_list<int> list) {
    cout << _(list)[2]; // subscript-like syntax for std::initializer_list!
}

int main() {
    f({1,2,3}); // prints: 3
    cout << _({1,2,3})[2]; // works also, prints: 3
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

需要注意的是,如果您运行 std::initializer_list 的许多项,则上面提供的解决方案在性能方面并不是一个好交易,因为上面建议类型的临时对象_init_list_with_square_brackets是重复创建的。这当然再次引发了为什么标准本身没有提供这一点的疑问。

  • 如果我会在代码中看到语法,我会立即成为“wtf”。我不知道`_`实际上是一个id,而不是表示一个函数。就像 rly,“wtf”。我可能最终会弄明白(“转到定义”是否适用于名为`_` 的 id ??),但这并不能减轻我对编写编码器的家人的强烈、快速和反复提及那。我的建议就是使用`list.begin()[i]`。我很抱歉拒绝投票,因为这是一个很酷的技巧,语言方面,但在实践中它会适得其反。 (8认同)