LINUX.ORG.RU

std::vector.emplace_back и структура с инициализированными полями

 


0

1

Помогите разобраться, не могу понять или нагуглить.

C++11. g++5.1

#include <vector>

struct A{
    int a;
    bool b;
    int c;
};

std::vector<A> v;

int main(int argc, const char * argv[])
{
    // v.emplace_back(1,true,3); // не работает
    // v.emplace_back({1,true,3}); // не работает

    v.emplace_back(A{1,true,3});
}

Работает.

Добавляю значения по умолчанию:

#include <vector>

struct A{
    int a {1};
    bool b {true};
    int c{};
};

std::vector<A> v;

int main(int argc, const char * argv[])
{
    v.emplace_back(A{1,true,3});
}

error: no matching function for call to 'A::A(<brace-enclosed initializer list>)'

Как добавить в вектор с помощью emplace_back структуру, у которой имеются значения полей по умолчанию, не добавляя к структуре конструктор, который принимает все члены?

★★

    // v.emplace_back({1,true,3}); // не работает

Для такого варианта нужен push_back.

Добавляю значения по умолчанию:

error: no matching function

УМВР. G++ 12.2, Clang 14.

В случае, когда все поля со значениями – просто emplace_back() без аргументов должен работать.

g++5.1

Может пора обновиться?

snizovtsev ★★★★★
()
Последнее исправление: snizovtsev (всего исправлений: 5)

Тут проблема не в векторе, а в том что неявно определённый aggregate конструктор генерится только если для полей классов нет дефолтных инициализаторов. Т.е. A a{1, true, 1}; - инициализация как раз вот таким конструктором, который отсутствует если есть поля с дефолтным значением.

Если есть возможность использовать C++20 - я бы использовал designated fields инициализацию: A a{.a{1}, .b{true}, c{3}};

sh0ckfile
()

Ну нужно ещё старее компиль взять, куда торопиться то. Теперь уже дефолтные значения не лишают объект звания «аггрегат» и аггрегатная инициализация будет работать v.emplace_back(A{1,true,3});.

Вот это v.emplace_back(1,true,3); // не работает разварачивается в условно что то типа new(address) Type(args); и так как раннее нельзя было использовать круглые скобки для аггрегатной иницализации, то была ошибка. Но теперь можно (вроде с цпп20) и будет компиляться.

v.emplace_back({1,true,3}); // не работает Правила шаблонов - тип чего-то в фигурных скобках не выводится автоматом, нужно указывать самому.

kvpfs ★★
()
Ответ на: комментарий от sh0ckfile

неявно определённый aggregate конструктор

Что ты несёшь, какой ещё aggregate конструктор?

A a{1, true, 1}; - инициализация как раз вот таким конструктором

Никаким тут конструктором не инициализируется.

utf8nowhere ★★★
()
Ответ на: комментарий от utf8nowhere

Узбагойся, там пропущено слово «для» =) Но в целом верно, согласен - такая инициализация не использует никакой неявный конструктор, я выразился некорректно. Подразумевал инициализацию конечно же.

sh0ckfile
()