Rozważ następujący kod:
struct A
{
// No data members
//...
};
template<typename T, size_t N>
struct B : A
{
T data[N];
}
Oto jak zainicjować B: B<int, 3> b = { {}, {1, 2, 3} };
Chcę uniknąć niepotrzebnego pustego {} dla klasy podstawowej. Jest to rozwiązanie proponowane przez Jarod42 tutaj , jednak nie działa z domyślnych elementów inicjacji: B<int, 3> b = {1, 2, 3};
jest w porządku, ale B<int, 3> b = {1};
nie jest: b.data[1]
i b.data[2]
nie są domyślnie ustawiony na 0 i wystąpi błąd kompilatora. Czy jest jakiś sposób (lub będzie z c ++ 20), aby „ukryć” klasę bazową przed budową?
c++
initialization
c++20
aggregate-initialization
użytkownik7769147
źródło
źródło
template<class... Ts> B(Ts... args) : data{args...} {}
?Odpowiedzi:
Najłatwiejszym rozwiązaniem jest dodanie konstruktora variadic:
Jeśli podasz mniej elementów na
{...}
liście inicjalizującej niżN
, pozostałe elementy w tablicydata
zostaną zainicjalizowane wartościami przezT()
.źródło
B<Class, 5> b = {Class()};
Class
że zostanie najpierw zbudowany, a następnie przeniesiony, podczas gdy przy użyciu agregacji inicjującejClass
byłby zbudowany, nie będzie żadnego ruchustd::tuple
argumenty i użyć ich do budowy obiektów w miejscu. Ale składnia będzie raczej nieporęczna.Od wersji C ++ 20 można używać wyznaczonych inicjatorów do agregacji inicjalizacji .
źródło
Nadal z konstruktorem możesz zrobić coś takiego:
Próbny
SFINAE odbywa się głównie w celu uniknięcia tworzenia konstruktora pseudo-kopii
B(B&)
.Potrzebujesz dodatkowego prywatnego tagu do wsparcia
B<std::index_sequence<0, 1>, 42>
;-)źródło
((void)Is, T())...
? Co jeśli po prostu to pominiesz? CzyT()
domyślnie nie zostaną zainicjowane pozostałe elementy ?Znalazłem inne rozwiązanie, które (nie wiem jak) działa idealnie i rozwiązuje problem, który omawialiśmy pod odpowiedzią Evga
źródło
this->data
lubusing B_data::data;
wejść dodata
środkaB
.