В C ++ 20 можно будет делать то, что вы пытаетесь сделать напрямую:
template <typename T, typename A = some_type_with_size_0>
struct s {
T t;
[[no_unique_address]] A aux;
};
См. https://en.cppreference.com/w/cpp/language/attributes/no_unique_address.
В C ++ 17 естьнет простого способа указать член, который условно исчезает.Вам необходимо написать полномасштабную частичную специализацию, например, так:
template <typename T, typename A = void>
struct s {
T t;
A aux;
};
template <typename T>
struct s<T, void> {
T t;
};
К сожалению, это требует от вас повторения ввода всех общих членов (в данном случае только t
).Чтобы избежать этого, мы можем вставить условно представленные члены в базовый класс:
template <typename T, typename A = void>
struct s : optional_aux<A> {
T t;
};
template <typename A>
struct optional_aux {
A aux;
};
template <>
struct optional_aux<void> { };
В случае, когда A = void
, этот базовый класс пуст, поэтому компилятор может по своему усмотрению удалить его полностью, делаяsizeof(s<T, void>)
потенциально равно sizeof(T)
.Атрибут [[no_unique_address]]
в основном делает пустую оптимизацию базового класса доступной и для членов.