为什么 C++ 使 std::initializer_list 的元素类型为常量?

Why does C++ make the element type of std::initializer_list const?

我通常使用 std::initializer_list<std::string>,比如说 {"foo"s, "bar"s},来填充一个容器。

显然,std::initializer_list<std::string> 包含临时字符串,我可以将它们移动到容器中:

#include <string>
#include <list>

using namespace std::literals;    

void f(std::initializer_list<std::string> il)
{
    std::list<std::string> coll;
    for (auto&& tmp_str : il)
    {
        coll.emplace_back(std::move(tmp_str)); // Why ok here?
    }
}

int main()
{
    f({"foo"s, "bar"s});
}

然而,根据cppref

An object of type std::initializer_list is a lightweight proxy object that provides access to an array of objects of type const T.

为什么C++要让std::initializer_list的元素类型为const?

Obviously, std::initializer_list<std::string> contains temporary strings

是吗?允许将其实现为瘦代理。在这种情况下,它将引用原始实例 "foo"s"bar"s.

... and I can move them into a container

我对此表示怀疑。 const 左值引用的 std::move() 产生... const 右值引用。这与作为可行候选者的移动构造函数不太匹配。

#include <iostream>

struct A {
    A() { std::cout << "A()\n"; }
    A(A&&) { std::cout << "A(&&)\n"; }
    A(A const&) { std::cout << "A(const&)\n"; }
};

int main() {
    const A a;
    A b(std::move(a));
}

版画

A()
A(const&)

MSVC 2019 甚至警告:

Warning C26478  Don't use std::move on constant variables. (es.56).

另见