Проблема со списком инициализаторов в конструкторе

Мне трудно понять, как работает std::initializer_list. Я проверила другие вопросы, но ничего подходящего не нашла (а может не увидела?).

Скажем, у меня есть это:

template<typename T> 
struct Point
{
    T x,y;
};

template<typename T> 
struct A
{
    std::vector<Point<T>> v;
};

Затем я могу построить с помощью:

int main()
{
   A<int> a{ std::vector<Point<int>> { {4,4}, {5,5},{6,6} } };
}

Но я хотел бы сделать все проще, поэтому я могу написать:

int main()
{
   A<int> a( { {4,4}, {5,5},{6,6} } );
}

Я пытался:

template<typename T> 
struct A
{
    std::vector<Point<T>> v;
    template<typename U>
    A( const std::initializer_list<Point<U>>& il ) : v{il}
    {}
};

Но это не получается, смотрите демо вживую.

Как я могу написать конструктор, позволяющий это? Это вообще возможно?

Стоит ли изучать 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 называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
2
0
182
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Ваши конструкторы не должны быть шаблонными, ваш класс уже есть. {..} не имеет типа и может быть сведен к очень небольшому количеству типов.

После удаления работает следующее:

template<typename T> 
struct A
{
    std::vector<Point<T>> v;

    A( const std::vector<Point<T>>& in ) : v(in) {}

    A( const std::initializer_list<Point<T>>& il ): v{il}
    {}
};

int main()
{
    std::vector<Point<int>> v{ {4,4}, {5,5},{6,6} };
    A<int> a1( std::vector<Point<int>> { {4,4}, {5,5},{6,6} } ); // this is fine
    assert( a1.v.size() == 3 );

    A<int> a2{{4,4}, {5,5}, {6,6} };
    assert( a2.v.size() == 3 );

    A<int> a3({{4,4}, {5,5}, {6,6} });
}

Демо

Спасибо! Действительно работает. Дело в том, что я создал шаблон конструктора для обработки возможности инициализации с другим типом FP ​​(за счет потенциальной потери точности). Произнесите что-нибудь вроде A<float> a{{4.4,5.5}}; и приступайте к копированию поэлементно в теле конструктора. Но меня устраивает решение с таким же типом!

kebs 07.02.2023 17:25

В C++20 есть функция, называемая инициализацией агрегатов в скобках, которая позволяет правильно формировать заданный синтаксис.

template<typename T> 
struct Point
{
    T x, y;
};

template<typename T> 
struct A
{
    std::vector<Point<T>> v;
    
};
int main()
{
//--------------v------------------------v---> parenthesis ok with c++20, replace () with {} for pre-c++20
        A<int> a( { {4, 4}, {5, 5}, {6, 6} } );
        
}

Рабочая демонстрация

Это означает, что если вы работаете с версиями до C++20, вы можете заменить круглые скобки () фигурными скобками {}. демо С++ 14

Благодарить! Но, похоже, для этого требуется С++ 20, а не С++ 17: ваша ссылка не работает при переключении на -std=c++17. Я бы предпочел придерживаться С++ 14.

kebs 07.02.2023 17:19
Ответ принят как подходящий

Во-первых, ваш желаемый синтаксис почти работает (без добавления конструктора к A), просто замените (...) на {...}.

int main()
{
   A<int> a{{ {4,4}, {5,5},{6,6} }};
}

Во-вторых, если вы все еще хотите написать конструктор для A, не используйте для него std::initializer_list! std::vector уже делает это, так что вам не нужно. Просто передайте вектор:

template<typename T> 
struct A
{
    std::vector<Point<T>> v;
    A(std::vector<Point<T>> v) : v(std::move(v)) {}
};

int main()
{
    A<int> a( { {4,4}, {5,5},{6,6} } );
}

Да, я действительно пропустил синтаксис двойных фигурных скобок, спасибо!

kebs 08.02.2023 07:44

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

Почему в С++ есть это правило: явные определения создания экземпляров игнорируют спецификаторы доступа к членам: типы параметров и возвращаемые типы могут быть закрытыми
Модель памяти «получить-освободить» для двух последовательных атомарных операций
Стандарт С++ для смещений элементов стандартной структуры макета
Почему в этом примере используется «2.» вместо «2.0» (десятичная точка без десятичных знаков)?
Используйте лямбда через ссылку std::function, вы не можете изменить значение в лямбда
Виртуальный метод в С++ не высмеивается. Что мне здесь не хватает?
=default и =delete - это объявление функции или определение функции?
Почему попытка напечатать строки в кодировке Unicode с помощью cout приводит к ошибке компиляции в новых стандартах C++?
Decltype оценивает неверный тип из списка выражений
Использование параметра шаблона против аргумента конструктора