Почему C ++ делает тип элемента std :: initializer_list const? - PullRequest
0 голосов
/ 07 апреля 2020

Я обычно использую 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 :

Объект типа std :: initializer_list является легким прокси-объектом, который обеспечивает доступ к массиву объектов типа const T.

Почему C ++ делает тип элемента std :: initializer_list const?

1 Ответ

1 голос
/ 07 апреля 2020

Очевидно, std::initializer_list<std::string> содержит временные строки

Правда ли это? Разрешается реализовывать его как тонкий прокси. В этом случае это будет относиться к исходным экземплярам "foo"s, "bar"s.

... и я могу переместить их в контейнер

Я сомневаюсь в этом. std::move() из const lvalue-reference создает ... const rvalue-reference. Это не совсем соответствует конструктору ходов как жизнеспособному кандидату.

#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&)

MSV C 2019 даже предупреждает:

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

См. Также Почему мы можем использовать std::move для const объекта?

...