简体   繁体   中英

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

I commonly use std::initializer_list<std::string> , say {"foo"s, "bar"s} , to fill a container.

Obviously, std::initializer_list<std::string> contains temporary strings, and I can move them into a container:

#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});
}

However, according to 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.

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

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

Does it, though? It is allowed to be implemented it as a thin proxy. In which case it would refer to the original instances "foo"s , "bar"s .

... and I can move them into a container

I doubt that. std::move() of a const lvalue-reference produces... a const rvalue-reference. That won't quite match a move-constructor as a viable candidate.

#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));
}

Prints

A()
A(const&)

MSVC 2019 even warns:

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

See also Why can we use std::move on a const object?

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM