เท่าที่ฉันสามารถบอกได้ว่าเป็นไปไม่ได้หากคุณต้องการมีสมาชิกทั้งคู่ แต่คุณสามารถชำนาญและมีสมาชิกได้เพียงคนเดียวเมื่อประเภทนั้นเหมือนกันและว่างเปล่า:
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; };
};
แน่นอนส่วนที่เหลือของโปรแกรมที่ใช้สมาชิกจะต้องมีการเปลี่ยนแปลงเพื่อจัดการกับกรณีที่มีสมาชิกเพียงคนเดียว ไม่สำคัญว่าสมาชิกรายใดจะใช้ในกรณีนี้เพราะเป็นวัตถุไร้สัญชาติที่ไม่มีที่อยู่เฉพาะ ฟังก์ชั่นสมาชิกที่แสดงควรทำให้ง่าย
น่าเสียดาย sizeof(Empty<Empty<A,A>,A>{})==2
ที่ A คือโครงสร้างที่ว่างเปล่าโดยสมบูรณ์
คุณสามารถแนะนำความเชี่ยวชาญพิเศษเพิ่มเติมเพื่อรองรับการบีบอัดแบบเรียกซ้ำของคู่ที่ว่างเปล่า:
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; };
};
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
ตัวเอง? ที่จะสร้างประเภทที่แตกต่าง ตอนนี้ความเป็นจริงที่ว่าทั้งสองWrapper
s สืบทอดจากT
ถือคุณกลับ ...