Каковы правила для структурированных автоматически определенных конструкторов в c ++ 17? - PullRequest
0 голосов
/ 03 июля 2018

Дано:

struct X {
  int m;
  std::string s;
};

Я могу сделать:

X x;  // invokes automatically defined default ctor
X y = { 5 };   // invokes whatever became of the original struct initialization but now maybe runs through C++ initializer-lists?
X z = { 5, "yolo" };  // I assume this is an initializer-list that is being handled by some rule for structs that either runs through a compiler created ctor or copy-from-initializer-list that is similarly compiler-created

и даже ...

std::vector<X> vx;
vx.push_back({ 99, "yo" }); // okay

Но не ...

vx.emplace_back(99, "yo");  // error VS 2017 v. 15.7.4
vx.emplace_back({99, "yo"});  // error VS 2017 v. 15.7.4

Я не понимаю правил между списками инициализаторов, неявно определенными (или определяемыми компилятором) ctors и функциями переадресации, такими как emplace_back()

Будет ли кто-то так любезен, чтобы указать мне на необходимые фрагменты стандарта или на хорошую статью о глубоком обсуждении того, что стало со всеми правилами вокруг структур и неявных конструкций и других предоставленных компилятором членов, таких как как операторы копирования / перемещения?

Кажется, мне нужен более полный урок правил - потому что кажется, что emplace_back() должен работать для одного из emplace_back(int, std::string) или для emplace_back(initializer-list) - нет?

1 Ответ

0 голосов
/ 03 июля 2018

X - это совокупность . Хотя конкретное определение агрегата изменилось в каждом стандарте, ваш тип является агрегатом во всех из них.

List-initialization для агрегата выполняет здесь агрегатную инициализацию. Здесь нет конструктора - нет авто-конструктора, нет синтезированного конструктора. Агрегированная инициализация не создает конструкторы и не проходит через этот механизм. Мы непосредственно инициализируем каждого члена класса из соответствующего инициализатора в braced-init-list . Это то, что делают и ваши y, и ваши z.

Теперь для второй части. Соответствующая часть vector выглядит так:

template <typename T>
struct vector {
    void push_back(T&&);

    template <typename... Args>
    void emplace_back(Args&&...);
};

A braced-init-list , как и {99, "yo"}, не имеет типа. И вы не можете вывести тип для этого. Они могут быть использованы только в определенных обстоятельствах. push_back({99, "yo"}) отлично работает, потому что push_back занимает X&& - это не шаблон функции - и мы знаем, как выполнить эту инициализацию.

Но emplace_back() - это шаблон функции - он должен вывести Args... из типов своих аргументов. Но у нас нет типа, нечего выводить! Здесь есть некоторые исключения (в частности, std::initializer_list<T> может быть выведено), но здесь мы застряли. Вам нужно будет написать emplace_back(X{99, "yo"}) - что создает X на стороне вызывающего.

Аналогично, emplace_back(99, "yo") не работает, потому что emplace использует () s для инициализации, но вы не можете () -инициализировать агрегат. У него нет конструктора!

...