From 35690469481a9bbdf8cc3d1e882fc5f82392e909 Mon Sep 17 00:00:00 2001 From: Johannes Stoelp Date: Fri, 5 Apr 2024 00:26:31 +0200 Subject: dtor: conditional trivial destructible --- cond_trivial_destr.cc | 94 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 94 insertions(+) create mode 100644 cond_trivial_destr.cc (limited to 'cond_trivial_destr.cc') diff --git a/cond_trivial_destr.cc b/cond_trivial_destr.cc new file mode 100644 index 0000000..8186e6b --- /dev/null +++ b/cond_trivial_destr.cc @@ -0,0 +1,94 @@ +#if 0 +set -xe +g++ -std=c++20 -fsyntax-only cond_trivial_destr.cc +clang++ -std=c++20 -fsyntax-only cond_trivial_destr.cc +exit 0 +#endif + +#include + +// Conditional trivial destructible. +// +// Since destructors can't have template parameters, std::enable_if can't be +// used to selectively enable or disable the destructor via SFINAE. +// +// If a template class wants to be trivially destructible depending on the +// template parameter, one has to work around it with some template +// specialization (pre cpp20). The implementation in the namespace v1 gives an +// example for that. +// +// Starting with cpp20 we can leverage concepts to enable / disable different +// destructor implementations. The implementations in the namespace v2 gives an +// example for that. + +// -- PRE CPP20 ---------------------------------------------------------------- + +namespace v1 { +template > +struct storage { + ~storage() { + if (has_val) { + val.~T(); + has_val = false; + } + } + + union { + T val; + }; + bool has_val = false; +}; + +template +struct storage { + union { + T val; + }; +}; + +template +struct option : private storage {}; +} // namespace v1 + +// -- SINCE CPP20 -------------------------------------------------------------- + +namespace v2 { +#if __cplusplus >= 202002L +template +struct option { + ~option() = default; + ~option() + requires(!std::is_trivially_destructible_v) + { + val.~T(); + } + +private: + union { + T val; + }; + bool has_value = false; +}; +#endif +} // namespace v2 + +// -- TESTEE ------------------------------------------------------------------- + +struct trivial {}; +static_assert(std::is_trivially_destructible_v, ""); + +struct non_trivial { + ~non_trivial() { + } +}; +static_assert(!std::is_trivially_destructible_v, ""); + +// -- TEST --------------------------------------------------------------------- + +static_assert(std::is_trivially_destructible_v>, ""); +static_assert(!std::is_trivially_destructible_v>, ""); + +#if __cplusplus >= 202002L +static_assert(std::is_trivially_destructible_v>, ""); +static_assert(!std::is_trivially_destructible_v>, ""); +#endif -- cgit v1.2.3