From 084151b6d1e857e7716b6abf2fdefacfa07956a3 Mon Sep 17 00:00:00 2001 From: Max Staff Date: Mon, 3 Feb 2020 15:57:16 +0100 Subject: [PATCH 1/3] Implementing is_variant_which Also moving Variant::Which to VariantWhich, which is necessary to create is_variant_which. --- src/variant17.lib/variant17/Variant.h | 71 ++++++++++--------- src/variant17.lib/variant17/Variant.test.cpp | 2 +- src/variant17.lib/variant17/Variant.trait.h | 6 ++ .../variant17/Variant.trait.test.cpp | 7 ++ 4 files changed, 52 insertions(+), 34 deletions(-) diff --git a/src/variant17.lib/variant17/Variant.h b/src/variant17.lib/variant17/Variant.h index db2db36..b2b1514 100644 --- a/src/variant17.lib/variant17/Variant.h +++ b/src/variant17.lib/variant17/Variant.h @@ -59,40 +59,50 @@ auto selectType() { template using SelectType = UnwrapType())>; -/// Variant != std::variant -/// * unchecked invalid state (only destruction is valid!) -/// * simple recursive vistor -/// * allows uncheck casts (you have to check before!) -/// * sizeof(index) limits template -struct Variant { +struct VariantWhich { static constexpr auto pack = to_type_pack; static constexpr auto indices = indexPackFor(pack); - using First = TypeHead; using WhichValue = UnwrapType>; // enough for npos! - enum { npos = sizeof...(Ts) }; // invalid state after exception - only destruction checks! + explicit constexpr VariantWhich(WhichValue v) + : value(v) {} - struct Which { - explicit constexpr Which(WhichValue v) - : value(v) {} + constexpr operator WhichValue() const { return value; } - constexpr operator WhichValue() const { return value; } + constexpr bool operator==(VariantWhich w) const { return w.value == value; } + constexpr bool operator!=(VariantWhich w) const { return w.value != value; } - constexpr bool operator==(Which w) const { return w.value == value; } - constexpr bool operator!=(Which w) const { return w.value != value; } + template + constexpr bool operator==(Type) const { + return whichOf() == *this; + } + template + constexpr bool operator!=(Type) const { + return whichOf() != *this; + } - template - constexpr bool operator==(Type) const { - return whichOf() == *this; - } - template - constexpr bool operator!=(Type) const { - return whichOf() != *this; - } + template + constexpr static auto whichOf(Type = {}) -> VariantWhich { + return VariantWhich{static_cast(indexedTypePackIndexOf(pack, indices))}; + } - private: - WhichValue value; - }; +private: + WhichValue value; +}; + +/// Variant != std::variant +/// * unchecked invalid state (only destruction is valid!) +/// * simple recursive vistor +/// * allows uncheck casts (you have to check before!) +/// * sizeof(index) limits +template +struct Variant { + using Which = VariantWhich; + static constexpr auto pack = Which::pack; + static constexpr auto indices = Which::indices; + using First = TypeHead; + using WhichValue = typename Which::WhichValue; + enum { npos = sizeof...(Ts) }; // invalid state after exception - only destruction checks! private: std::aligned_union_t<0, Ts...> m{}; @@ -171,7 +181,7 @@ struct Variant { Variant(T&& t) { static_assert(containsOf(pack), "type not part of variant"); constructOf(type, std::forward(t)); - whichValue = whichOf(); + whichValue = Which::whichOf(type); } /// inplace construct of type @@ -179,7 +189,7 @@ struct Variant { Variant(Type, Args&&... args) { static_assert(containsOf(pack), "type not part of variant"); constructOf(type, std::forward(args)...); - whichValue = whichOf(); + whichValue = Which::whichOf(type); } template @@ -207,12 +217,7 @@ struct Variant { if (whichValue != npos) destruct(); whichValue = npos; constructOf(type, std::forward(args)...); - whichValue = whichOf(); - } - - template - constexpr static auto whichOf(Type = {}) -> Which { - return Which{static_cast(indexedTypePackIndexOf(pack, indices))}; + whichValue = Which::whichOf(type); } template diff --git a/src/variant17.lib/variant17/Variant.test.cpp b/src/variant17.lib/variant17/Variant.test.cpp index e47ec9d..f169619 100644 --- a/src/variant17.lib/variant17/Variant.test.cpp +++ b/src/variant17.lib/variant17/Variant.test.cpp @@ -76,7 +76,7 @@ TEST(Variant, which) { ASSERT_NE(v.which(), type); ASSERT_EQ(v.which(), type); - static_assert(V::whichOf() == type); + static_assert(V::Which::whichOf() == type); // Should not compile due to double is not part of V // static_assert(V::whichOf() == type); } diff --git a/src/variant17.lib/variant17/Variant.trait.h b/src/variant17.lib/variant17/Variant.trait.h index e62b708..164fad8 100644 --- a/src/variant17.lib/variant17/Variant.trait.h +++ b/src/variant17.lib/variant17/Variant.trait.h @@ -9,4 +9,10 @@ constexpr auto is_variant = false; template constexpr auto is_variant> = true; +template +constexpr auto is_variant_which = false; + +template +constexpr auto is_variant_which> = true; + } // namespace variant17 diff --git a/src/variant17.lib/variant17/Variant.trait.test.cpp b/src/variant17.lib/variant17/Variant.trait.test.cpp index de0d50a..0a6333e 100644 --- a/src/variant17.lib/variant17/Variant.trait.test.cpp +++ b/src/variant17.lib/variant17/Variant.trait.test.cpp @@ -8,14 +8,21 @@ using namespace variant17; TEST(Variant, trait) { using T = Variant; static_assert(is_variant); + static_assert(!is_variant_which); + + static_assert(!is_variant); + static_assert(is_variant_which); struct S { int i; }; static_assert(!is_variant); + static_assert(!is_variant_which); using P = std::pair; static_assert(!is_variant

); + static_assert(!is_variant_which

); static_assert(!is_variant); + static_assert(!is_variant_which); } From 0ee2656cc4ccc55a936e11e824b1eaac5859ed80 Mon Sep 17 00:00:00 2001 From: Max Staff Date: Mon, 3 Feb 2020 19:14:42 +0100 Subject: [PATCH 2/3] Adding default constructor to VariantWhich. --- src/variant17.lib/variant17/Variant.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/variant17.lib/variant17/Variant.h b/src/variant17.lib/variant17/Variant.h index b2b1514..f35160b 100644 --- a/src/variant17.lib/variant17/Variant.h +++ b/src/variant17.lib/variant17/Variant.h @@ -64,6 +64,9 @@ struct VariantWhich { static constexpr auto pack = to_type_pack; static constexpr auto indices = indexPackFor(pack); using WhichValue = UnwrapType>; // enough for npos! + + constexpr VariantWhich() + : value(0) {} explicit constexpr VariantWhich(WhichValue v) : value(v) {} From 159859ac783c04fdfb5dc0aa9827a34039dbb1cc Mon Sep 17 00:00:00 2001 From: Max Staff Date: Mon, 10 Feb 2020 14:43:37 +0100 Subject: [PATCH 3/3] Implementing requested changes --- src/variant17.lib/variant17/Variant.h | 23 ++++++++++++-------- src/variant17.lib/variant17/Variant.test.cpp | 2 +- 2 files changed, 15 insertions(+), 10 deletions(-) diff --git a/src/variant17.lib/variant17/Variant.h b/src/variant17.lib/variant17/Variant.h index f35160b..0d403c2 100644 --- a/src/variant17.lib/variant17/Variant.h +++ b/src/variant17.lib/variant17/Variant.h @@ -59,14 +59,14 @@ auto selectType() { template using SelectType = UnwrapType())>; +/// VariantWhich is an enum-like type used in Variant to determine which type is currently present in the Variant. template struct VariantWhich { static constexpr auto pack = to_type_pack; static constexpr auto indices = indexPackFor(pack); using WhichValue = UnwrapType>; // enough for npos! - constexpr VariantWhich() - : value(0) {} + constexpr VariantWhich() = default; explicit constexpr VariantWhich(WhichValue v) : value(v) {} @@ -77,20 +77,20 @@ struct VariantWhich { template constexpr bool operator==(Type) const { - return whichOf() == *this; + return of() == *this; } template constexpr bool operator!=(Type) const { - return whichOf() != *this; + return of() != *this; } template - constexpr static auto whichOf(Type = {}) -> VariantWhich { + constexpr static auto of(Type = {}) -> VariantWhich { return VariantWhich{static_cast(indexedTypePackIndexOf(pack, indices))}; } private: - WhichValue value; + WhichValue value{}; }; /// Variant != std::variant @@ -184,7 +184,7 @@ struct Variant { Variant(T&& t) { static_assert(containsOf(pack), "type not part of variant"); constructOf(type, std::forward(t)); - whichValue = Which::whichOf(type); + whichValue = whichOf(type); } /// inplace construct of type @@ -192,7 +192,7 @@ struct Variant { Variant(Type, Args&&... args) { static_assert(containsOf(pack), "type not part of variant"); constructOf(type, std::forward(args)...); - whichValue = Which::whichOf(type); + whichValue = whichOf(type); } template @@ -220,7 +220,12 @@ struct Variant { if (whichValue != npos) destruct(); whichValue = npos; constructOf(type, std::forward(args)...); - whichValue = Which::whichOf(type); + whichValue = whichOf(type); + } + + template + constexpr static auto whichOf(Type = {}) -> Which { + return Which::of(type); } template diff --git a/src/variant17.lib/variant17/Variant.test.cpp b/src/variant17.lib/variant17/Variant.test.cpp index f169619..e47ec9d 100644 --- a/src/variant17.lib/variant17/Variant.test.cpp +++ b/src/variant17.lib/variant17/Variant.test.cpp @@ -76,7 +76,7 @@ TEST(Variant, which) { ASSERT_NE(v.which(), type); ASSERT_EQ(v.which(), type); - static_assert(V::Which::whichOf() == type); + static_assert(V::whichOf() == type); // Should not compile due to double is not part of V // static_assert(V::whichOf() == type); }