From 50c5fb41c1080c6f555e76b6aa5414a61ad197cf Mon Sep 17 00:00:00 2001 From: Ben Deane Date: Thu, 29 May 2025 14:01:33 -0600 Subject: [PATCH] :sparkles: Add easy way to select optional implementation Problem: - Sometimes it's desirable to select `stdx::optional` or `std::optional` based on whether tombstone_traits is specialized or not. Solution: - Add a `specialized` typedef to the primary template for tombstone_traits to allow easy identification. --- include/stdx/optional.hpp | 10 +++++++--- test/optional.cpp | 16 ++++++++++++++++ 2 files changed, 23 insertions(+), 3 deletions(-) diff --git a/include/stdx/optional.hpp b/include/stdx/optional.hpp index 29912ca..042b64d 100644 --- a/include/stdx/optional.hpp +++ b/include/stdx/optional.hpp @@ -15,9 +15,12 @@ namespace stdx { inline namespace v1 { template struct tombstone_traits { - static_assert( - stdx::always_false_v, - "To use stdx::optional you must specialize stdx::tombstone_traits"); + using unspecialized = int; + constexpr auto operator()() const { + static_assert( + stdx::always_false_v, + "To use stdx::optional you must specialize stdx::tombstone_traits"); + } }; template @@ -47,6 +50,7 @@ template > class optional { not stdx::is_specialization_of_v, "Don't define tombstone traits for plain integral types"); constexpr static inline auto traits = TS{}; + using check_specialization_t [[maybe_unused]] = decltype(traits()); T val{traits()}; public: diff --git a/test/optional.cpp b/test/optional.cpp index 87fdcd7..cc84f10 100644 --- a/test/optional.cpp +++ b/test/optional.cpp @@ -427,3 +427,19 @@ TEST_CASE("tombstone with non-structural value", "[optional]") { CHECK(*o == std::string_view{}); } #endif + +#if __cplusplus >= 202002L +namespace { +template +using my_optional = stdx::conditional_t::unspecialized; +}, std::optional, stdx::optional>; +} // namespace + +TEST_CASE("select optional implementation based on whether tombstone traits " + "are present", + "[optional]") { + static_assert(std::is_same_v, stdx::optional>); + static_assert(std::is_same_v, std::optional>); +} +#endif