Совокупная инициализация 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?
@DmitryGordon Мне нужен этот базовый класс. случай, который я предоставил, является лишь минимальным примером
До С++ 17 у вас не может быть базовых классов, так что это не проблема. Вы бы просто поместили класс и все его операторы в пространство имен.
Для чего именно вы используете базовый класс? Функции сравнения должны быть переопределены в производном классе, чтобы они работали.
Что касается ошибок, которые вы показываете, то же самое, например, с. std::array
: вам нужна внешняя пара фигурных скобок для самого объекта, а затем внутренняя пара для совокупных данных. Как в der_pod<int, 2> dp{{3, 3}};
. Но это не сработает, потому что наследование и необходимость также инициализировать базовый класс (что приводит к этому начальному пустому {}
).
@NathanOliver Извините за поздний ответ. если база является шаблонным классом, здесь будет полезен CRTP
Вы все еще можете предоставить конструктор, например:
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: конструктор шаблонов с переменным числом аргументов действительно может быть альтернативой, но с этим нужно сделать оговорку, чтобы избежать проблем с конструктором копирования.
Ах, хороший момент! Но я думаю, что альтернативная версия с явно заданным по умолчанию конструктором копирования не так уж и плоха: godbolt.org/z/o6j4sjPc6. Если вы не обнаружите в этом что-то изначально неправильное, я думаю, это следует добавить к вашему ответу +1.
Я бы заметил, что в вашем примере нет ничего, связанного с наличием базового класса, вы можете удалить его и увидеть, что ошибка все еще существует godbolt.org/z/0FpuQ5