Theo như tôi có thể nói, điều đó là không thể nếu bạn muốn có cả hai thành viên. Nhưng bạn có thể chuyên môn hóa và chỉ có một trong số các thành viên khi loại giống nhau và trống:
template <typename T, typename S, typename = void>
struct Empty{
[[no_unique_address]] T t;
[[no_unique_address]] S s;
constexpr T& get_t() noexcept { return t; };
constexpr S& get_s() noexcept { return s; };
};
template<typename TS>
struct Empty<TS, TS, typename std::enable_if_t<std::is_empty_v<TS>>>{
[[no_unique_address]] TS ts;
constexpr TS& get_t() noexcept { return ts; };
constexpr TS& get_s() noexcept { return ts; };
};
Tất nhiên, phần còn lại của chương trình sử dụng các thành viên sẽ cần phải được thay đổi để giải quyết trường hợp chỉ có một thành viên. Không quan trọng thành viên nào được sử dụng trong trường hợp này - xét cho cùng, đó là một đối tượng không quốc tịch không có địa chỉ duy nhất. Các chức năng thành viên được hiển thị sẽ làm cho đơn giản.
Thật không may sizeof(Empty<Empty<A,A>,A>{})==2
, nơi A là một cấu trúc hoàn toàn trống rỗng.
Bạn có thể giới thiệu thêm các chuyên ngành để hỗ trợ nén đệ quy các cặp trống:
template<class TS>
struct Empty<Empty<TS, TS>, TS, typename std::enable_if_t<std::is_empty_v<TS>>>{
[[no_unique_address]] Empty<TS, TS> ts;
constexpr Empty<TS, TS>& get_t() noexcept { return ts; };
constexpr TS& get_s() noexcept { return ts.get_s(); };
};
template<class TS>
struct Empty<TS, Empty<TS, TS>, typename std::enable_if_t<std::is_empty_v<TS>>>{
[[no_unique_address]] Empty<TS, TS> ts;
constexpr TS& get_t() noexcept { return ts.get_t(); };
constexpr Empty<TS, TS>& get_s() noexcept { return ts; };
};
Thậm chí nhiều hơn, để nén một cái gì đó như Empty<Empty<A, char>, A>
.
template <typename T, typename S>
struct Empty<Empty<T, S>, S, typename std::enable_if_t<std::is_empty_v<S>>>{
[[no_unique_address]] Empty<T, S> ts;
constexpr Empty<T, S>& get_t() noexcept { return ts; };
constexpr S& get_s() noexcept { return ts.get_s(); };
};
template <typename T, typename S>
struct Empty<Empty<S, T>, S, typename std::enable_if_t<std::is_empty_v<S>>>{
[[no_unique_address]] Empty<S, T> st;
constexpr Empty<S, T>& get_t() noexcept { return st; };
constexpr S& get_s() noexcept { return st.get_t(); };
};
template <typename T, typename S>
struct Empty<T, Empty<T, S>, typename std::enable_if_t<std::is_empty_v<T>>>{
[[no_unique_address]] Empty<T, S> ts;
constexpr T& get_t() noexcept { return ts.get_t(); };
constexpr Empty<T, S> get_s() noexcept { return ts; };
};
template <typename T, typename S>
struct Empty<T, Empty<S, T>, typename std::enable_if_t<std::is_empty_v<T>>>{
[[no_unique_address]] Empty<S, T> st;
constexpr T& get_t() noexcept { return st.get_s(); };
constexpr Empty<S, T> get_s() noexcept { return st; };
};
T
chính nó? Điều đó sẽ tạo ra các loại khác nhau. Ngay bây giờ thực tế là cả haiWrapper
thừa kế từT
đang giữ bạn lại ...