Как избежать {} при использовании агрегатной инициализации с пустым базовым классом

Совокупная инициализация C++17 для базового класса великолепна, но она многословна, когда база предназначена только для предоставления некоторых функций (поэтому нет элементов данных).

Вот минимальный пример:

#include <cstddef>
struct base_pod
{
    // functions like friend compare operator
};
template<typename T, std::size_t N>
struct der_pod : public base_pod
{
    T k[N];
};

int main()
{
    der_pod<int, 2> dp {{}, {3, 3} };
}

Как показывает приведенный выше пример, я должен указать пустой {}, иначе возникнет ошибка компиляции. живая демонстрация. Если я пропущу это:

prog.cc:15:28: error: initializer for aggregate with no elements requires explicit braces
        der_pod<int, 2> dp{3, 3};
                           ^
prog.cc:15:31: warning: suggest braces around initialization of subobject [-Wmissing-braces]
        der_pod<int, 2> dp{3, 3};
                              ^
                              {}
1 warning and 1 error generated.

Любое обходное решение или способ до С++ 17?

Я бы заметил, что в вашем примере нет ничего, связанного с наличием базового класса, вы можете удалить его и увидеть, что ошибка все еще существует godbolt.org/z/0FpuQ5

Dmitry Gordon 09.04.2019 14:22

@DmitryGordon Мне нужен этот базовый класс. случай, который я предоставил, является лишь минимальным примером

Chen Li 09.04.2019 14:24

До С++ 17 у вас не может быть базовых классов, так что это не проблема. Вы бы просто поместили класс и все его операторы в пространство имен.

NathanOliver 09.04.2019 14:36

Для чего именно вы используете базовый класс? Функции сравнения должны быть переопределены в производном классе, чтобы они работали.

NathanOliver 09.04.2019 14:40

Что касается ошибок, которые вы показываете, то же самое, например, с. std::array: вам нужна внешняя пара фигурных скобок для самого объекта, а затем внутренняя пара для совокупных данных. Как в der_pod<int, 2> dp{{3, 3}};. Но это не сработает, потому что наследование и необходимость также инициализировать базовый класс (что приводит к этому начальному пустому {}).

Some programmer dude 09.04.2019 14:43

@NathanOliver Извините за поздний ответ. если база является шаблонным классом, здесь будет полезен CRTP

Chen Li 13.04.2019 03:19
Стоит ли изучать 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 называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
9
6
524
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

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

Вы все еще можете предоставить конструктор, например:

template <typename T, std::size_t N> using always_t = T;

struct base_pod
{
    // functions like friend compare operator
};
template<typename T, typename Seq> struct der_pod_impl;

template<typename T, std::size_t ... Is>
struct der_pod_impl<T, std::index_sequence<Is...>> : base_pod
{
    der_pod_impl(always_t<T, Is>... args) : k{args...} {}

    T k[sizeof...(Is)];
};

template<typename T, std::size_t N>
using der_pod = der_pod_impl<T, std::make_index_sequence<N>>;

Демо

Зачем преодолевать все трудности с разделением der_pod на шаблон псевдонима и вариант _impl, его специализацию и написание индивидуальной черты типа идентичности типа? Разве руководство по дедукции не может выполнить все это, одновременно включив CTAD (поэтому нет необходимости явно указывать тип и размер)?

303 25.12.2021 21:14

@ 303: конструктор шаблонов с переменным числом аргументов действительно может быть альтернативой, но с этим нужно сделать оговорку, чтобы избежать проблем с конструктором копирования.

Jarod42 25.12.2021 23:30

Ах, хороший момент! Но я думаю, что альтернативная версия с явно заданным по умолчанию конструктором копирования не так уж и плоха: godbolt.org/z/o6j4sjPc6. Если вы не обнаружите в этом что-то изначально неправильное, я думаю, это следует добавить к вашему ответу +1.

303 26.12.2021 01:01

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