Почему я не могу использовать std::vector::emplace_back без явного создания промежуточного объекта, хотя создание экземпляра работает и без него?

Я использую класс OneOrMoreIntHelper, который принимает как одно целое число, так и список инициализаторов целых чисел, и который отлично работает для создания экземпляров Class с помощью одного конструктора.

Однако при попытке использовать emplace_back это не удается. Например, этот пример кода не компилируется, выдавая сообщение об ошибке.

нет соответствующей функции для вызова std::vector::emplace_back()

#include <initializer_list>
#include <vector>

struct OneOrMoreIntHelper {
    OneOrMoreIntHelper(const int value) {}
    OneOrMoreIntHelper(const std::initializer_list<int> &) {}
};

struct Class {
    Class(OneOrMoreIntHelper) {}
};

void foo() {
    Class single_int(0);
    Class list_two_ints({0, 0});

    std::vector<Class> instances;
    // this works fine
    instances.emplace_back(0);
    
    // error: no matching function for call to ‘std::vector::emplace_back()’
    instances.emplace_back({0, 0}); 
    
    // Workaround
    instances.push_back(OneOrMoreIntHelper{0, 0});
}

Я нашел обходной путь выше, но в идеале мне бы вообще не приходилось создавать экземпляр объекта OneOrMoreIntHelper (в конце концов, весь смысл в том, чтобы иметь возможность набирать 0 вместо {0}, поэтому необходимость вводить OneOrMoreIntHelper{0, 0} в другом месте — полное поражение) цель).

Полный журнал сборки:

main.cpp: In function ‘void foo()’:
main.cpp:22:27: error: no matching function for call to ‘std::vector::emplace_back()’
   22 |     instances.emplace_back({0, 0});
      |     ~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~
In file included from /usr/include/c++/11/vector:72,
                 from main.cpp:2:
/usr/include/c++/11/bits/vector.tcc:109:7: note: candidate: ‘std::vector<_Tp, _Alloc>::reference std::vector<_Tp, _Alloc>::emplace_back(_Args&& ...) [with _Args = {}; _Tp = Class; _Alloc = std::allocator; std::vector<_Tp, _Alloc>::reference = Class&]’
  109 |       vector<_Tp, _Alloc>::
      |       ^~~~~~~~~~~~~~~~~~~
/usr/include/c++/11/bits/vector.tcc:109:7: note:   candidate expects 0 arguments, 1 provided

Вы должны добавить сообщение об ошибке к вопросу.

HolyBlackCat 10.05.2024 11:17

@HolyBlackCat 5-я строка снизу в примере кода, но я могу добавить ее в основной текст.

bers 10.05.2024 11:18

Пожалуйста, скопируйте и вставьте полный журнал сборки. Там будет больше информации об ошибке, которая необходима нам, чтобы правильно понять, что происходит.

Some programmer dude 10.05.2024 11:19

Должно быть актуально: stackoverflow.com/a/51789089/4123703

Louis Go 10.05.2024 11:25
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
4
65
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Причина, по которой instances.emplace_back({0, 0}); терпит неудачу, заключается в том, что emplace_back является шаблоном функции, и вы не можете вывести параметры ее шаблона из списка инициализаторов. См. также Почему мой шаблон не принимает список инициализаторов . Точнее, это невозможно, потому что это невыведенный контекст (см. этот ответ, заголовок 6).

Однако вы можете написать:

instances.emplace_back(std::initializer_list<int>{0, 0});
// or
auto list = {0, 0};
instances.emplace_back(list); 

Это похоже на Размещение вектора со списком инициализаторов

Другие вопросы по теме