lichray created this revision. lichray added reviewers: EricWF, mpark, mclow.lists. Herald added a subscriber: christof.
"Boolshit shall not prevail," LEWG says. References: http://wg21.link/P0608R1 Repository: rCXX libc++ https://reviews.llvm.org/D44865 Files: include/variant test/std/utilities/variant/variant.variant/variant.assign/T.pass.cpp test/std/utilities/variant/variant.variant/variant.ctor/T.pass.cpp
Index: test/std/utilities/variant/variant.variant/variant.ctor/T.pass.cpp =================================================================== --- test/std/utilities/variant/variant.variant/variant.ctor/T.pass.cpp +++ test/std/utilities/variant/variant.variant/variant.ctor/T.pass.cpp @@ -20,6 +20,7 @@ #include <string> #include <type_traits> #include <variant> +#include <memory> #include "test_convertible.hpp" #include "test_macros.h" @@ -53,7 +54,7 @@ void test_T_ctor_sfinae() { { - using V = std::variant<long, unsigned>; + using V = std::variant<long, long long>; static_assert(!std::is_constructible<V, int>::value, "ambiguous"); } { @@ -66,6 +67,16 @@ "no matching constructor"); } { + using V = std::variant<std::string, float>; + static_assert(!std::is_constructible<V, int>::value, + "no matching constructor"); + } + { + using V = std::variant<std::unique_ptr<int>, bool>; + static_assert(!std::is_constructible<V, std::unique_ptr<char>>::value, + "no explicit bool in constructor"); + } + { using V = std::variant<AnyConstructible, NoConstructible>; static_assert( !std::is_constructible<V, std::in_place_type_t<NoConstructible>>::value, @@ -99,6 +110,21 @@ static_assert(v.index() == 1, ""); static_assert(std::get<1>(v) == 42, ""); } + { + constexpr std::variant<unsigned, long> v(42); + static_assert(v.index() == 1, ""); + static_assert(std::get<1>(v) == 42, ""); + } + { + std::variant<std::string, bool const> v = "foo"; + assert(v.index() == 0); + assert(std::get<0>(v) == "foo"); + } + { + std::variant<bool volatile, std::unique_ptr<int>> v = nullptr; + assert(v.index() == 1); + assert(std::get<1>(v) == nullptr); + } #if !defined(TEST_VARIANT_HAS_NO_REFERENCES) { using V = std::variant<const int &, int &&, long>; Index: test/std/utilities/variant/variant.variant/variant.assign/T.pass.cpp =================================================================== --- test/std/utilities/variant/variant.variant/variant.assign/T.pass.cpp +++ test/std/utilities/variant/variant.variant/variant.assign/T.pass.cpp @@ -28,6 +28,7 @@ #include <string> #include <type_traits> #include <variant> +#include <memory> #include "test_macros.h" #include "variant_test_helpers.hpp" @@ -128,7 +129,7 @@ void test_T_assignment_sfinae() { { - using V = std::variant<long, unsigned>; + using V = std::variant<long, long long>; static_assert(!std::is_assignable<V, int>::value, "ambiguous"); } { @@ -139,6 +140,15 @@ using V = std::variant<std::string, void *>; static_assert(!std::is_assignable<V, int>::value, "no matching operator="); } + { + using V = std::variant<std::string, float>; + static_assert(!std::is_assignable<V, int>::value, "no matching operator="); + } + { + using V = std::variant<std::unique_ptr<int>, bool>; + static_assert(!std::is_assignable<V, std::unique_ptr<char>>::value, + "no explicit bool in operator="); + } #if !defined(TEST_VARIANT_HAS_NO_REFERENCES) { using V = std::variant<int, int &&>; @@ -167,6 +177,33 @@ assert(v.index() == 1); assert(std::get<1>(v) == 43); } + { + std::variant<unsigned, long> v; + v = 42; + assert(v.index() == 1); + assert(std::get<1>(v) == 42); + v = 43u; + assert(v.index() == 0); + assert(std::get<0>(v) == 43); + } + { + std::variant<std::string, bool> v = true; + v = std::false_type(); + assert(v.index() == 1); + assert(std::get<1>(v) == false); + v = "bar"; + assert(v.index() == 0); + assert(std::get<0>(v) == "bar"); + } + { + std::variant<bool, std::unique_ptr<int>> v; + v = nullptr; + assert(v.index() == 1); + assert(std::get<1>(v) == nullptr); + v = std::true_type(); + assert(v.index() == 0); + assert(std::get<0>(v)); + } #if !defined(TEST_VARIANT_HAS_NO_REFERENCES) { using V = std::variant<int &, int &&, long>; Index: include/variant =================================================================== --- include/variant +++ include/variant @@ -1092,16 +1092,42 @@ struct __overload; template <> -struct __overload<> { void operator()() const; }; +struct __overload<> +{ + static void test(); +}; template <class _Tp, class... _Types> -struct __overload<_Tp, _Types...> : __overload<_Types...> { - using __overload<_Types...>::operator(); - __identity<_Tp> operator()(_Tp) const; +struct __overload<_Tp, _Types...> : __overload<_Types...> +{ + using __overload<_Types...>::test; + + template <class _Up> + static auto test(_Tp, _Up&& __t) -> decltype(_Tp{__t}, __identity<_Tp>()); }; +#define _LIBCPP_VARIANT_BOOLEAN_CONVERSION(bool_type) \ + template <class... _Types> \ + struct __overload<bool_type, _Types...> : __overload<_Types...> \ + { \ + using __overload<_Types...>::test; \ + \ + template <class _Up, class _Ap = __uncvref_t<_Up>> \ + static auto test(bool, _Up&&) -> enable_if_t< \ + disjunction_v<is_same<_Ap, bool>, is_class<_Ap>, is_union<_Ap>>, \ + __identity<bool_type>>; \ + } + +_LIBCPP_VARIANT_BOOLEAN_CONVERSION(bool); +_LIBCPP_VARIANT_BOOLEAN_CONVERSION(bool const); +_LIBCPP_VARIANT_BOOLEAN_CONVERSION(bool volatile); +_LIBCPP_VARIANT_BOOLEAN_CONVERSION(bool const volatile); + +#undef _LIBCPP_VARIANT_BOOLEAN_CONVERSION + template <class _Tp, class... _Types> -using __best_match_t = typename result_of_t<__overload<_Types...>(_Tp&&)>::type; +using __best_match_t = typename decltype( + __overload<_Types...>::test(declval<_Tp>(), declval<_Tp>()))::type; } // __variant_detail
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits