diff options
author | Eric Fiselier <eric@efcs.ca> | 2019-03-31 20:49:06 +0000 |
---|---|---|
committer | Eric Fiselier <eric@efcs.ca> | 2019-03-31 20:49:06 +0000 |
commit | b0e79823d699d9a0c65edb7f425d55a305cccde3 (patch) | |
tree | 9a86a30e2643f9516095b89bbbae930baa13f5c3 /libcxx/test/std/utilities/meta | |
parent | 76829d8928790d573e0bdc2dc1a2f042ecb8eeaa (diff) | |
download | bcm5719-llvm-b0e79823d699d9a0c65edb7f425d55a305cccde3.tar.gz bcm5719-llvm-b0e79823d699d9a0c65edb7f425d55a305cccde3.zip |
Make common_type's implementation common
Summary:
Currently the C++03 implementation of common_type has much different behavior than the C++11 one. This causes bugs, including inside `<chrono>`.
This patch unifies the two implementations as best it can. The more code they share, the less their behavior can diverge.
Reviewers: mclow.lists, ldionne, sbenza
Reviewed By: mclow.lists, ldionne
Subscribers: libcxx-commits
Tags: #libc
Differential Revision: https://reviews.llvm.org/D59678
llvm-svn: 357370
Diffstat (limited to 'libcxx/test/std/utilities/meta')
-rw-r--r-- | libcxx/test/std/utilities/meta/meta.trans/meta.trans.other/common_type.pass.cpp | 175 |
1 files changed, 98 insertions, 77 deletions
diff --git a/libcxx/test/std/utilities/meta/meta.trans/meta.trans.other/common_type.pass.cpp b/libcxx/test/std/utilities/meta/meta.trans/meta.trans.other/common_type.pass.cpp index f96603b30b6..a6b2f6244a2 100644 --- a/libcxx/test/std/utilities/meta/meta.trans/meta.trans.other/common_type.pass.cpp +++ b/libcxx/test/std/utilities/meta/meta.trans/meta.trans.other/common_type.pass.cpp @@ -48,40 +48,53 @@ namespace std template <> struct common_type< ::X<double>, ::X<double> > {}; } -#if TEST_STD_VER >= 11 +template <class> struct VoidT { typedef void type; }; + +#if TEST_STD_VER < 11 +template <class Trait, class = void> +struct no_common_type_imp : std::true_type {}; + +template <class Trait> +struct no_common_type_imp<Trait, typename VoidT<typename Trait::type>::type> + : std::false_type {}; + +struct NoArgTag; + +template <class Tp = NoArgTag, class Up = NoArgTag, class Vp = NoArgTag> +struct no_common_type : no_common_type_imp<std::common_type<Tp, Up, Vp> > {}; +template <class Tp, class Up> +struct no_common_type<Tp, Up> : no_common_type_imp<std::common_type<Tp, Up> > { +}; +template <class Tp> +struct no_common_type<Tp> : no_common_type_imp<std::common_type<Tp> > {}; +template <> +struct no_common_type<> : no_common_type_imp<std::common_type<> > {}; +#else template <class Tp> struct always_bool_imp { using type = bool; }; template <class Tp> using always_bool = typename always_bool_imp<Tp>::type; template <class ...Args> constexpr auto no_common_type_imp(int) - -> always_bool<typename std::common_type<Args...>::type> - { return false; } +-> always_bool<typename std::common_type<Args...>::type> +{ return false; } template <class ...Args> constexpr bool no_common_type_imp(long) { return true; } template <class ...Args> using no_common_type = std::integral_constant<bool, no_common_type_imp<Args...>(0)>; - -template <class Tp> -using Decay = typename std::decay<Tp>::type; - -template <class ...Args> -using CommonType = typename std::common_type<Args...>::type; +#endif template <class T1, class T2> -struct TernaryOpImp { - static_assert(std::is_same<Decay<T1>, T1>::value, "must be same"); - static_assert(std::is_same<Decay<T2>, T2>::value, "must be same"); - using type = typename std::decay< +struct TernaryOp { + static_assert((std::is_same<typename std::decay<T1>::type, T1>::value), "must be same"); + static_assert((std::is_same<typename std::decay<T2>::type, T2>::value), "must be same"); + typedef typename std::decay< decltype(false ? std::declval<T1>() : std::declval<T2>()) - >::type; + >::type type; }; -template <class T1, class T2> -using TernaryOp = typename TernaryOpImp<T1, T2>::type; - // -- If sizeof...(T) is zero, there shall be no member type. void test_bullet_one() { static_assert(no_common_type<>::value, ""); @@ -90,23 +103,23 @@ void test_bullet_one() { // If sizeof...(T) is one, let T0 denote the sole type constituting the pack T. // The member typedef-name type shall denote the same type as decay_t<T0>. void test_bullet_two() { - static_assert(std::is_same<CommonType<void>, void>::value, ""); - static_assert(std::is_same<CommonType<int>, int>::value, ""); - static_assert(std::is_same<CommonType<int const>, int>::value, ""); - static_assert(std::is_same<CommonType<int volatile[]>, int volatile*>::value, ""); - static_assert(std::is_same<CommonType<void(&)()>, void(*)()>::value, ""); + static_assert((std::is_same<std::common_type<void>::type, void>::value), ""); + static_assert((std::is_same<std::common_type<int>::type, int>::value), ""); + static_assert((std::is_same<std::common_type<int const>::type, int>::value), ""); + static_assert((std::is_same<std::common_type<int volatile[]>::type, int volatile*>::value), ""); + static_assert((std::is_same<std::common_type<void(&)()>::type, void(*)()>::value), ""); - static_assert(no_common_type<X<double> >::value, ""); + static_assert((no_common_type<X<double> >::value), ""); } template <class T, class U, class Expect> void test_bullet_three_one_imp() { - using DT = Decay<T>; - using DU = Decay<U>; - static_assert(!std::is_same<T, DT>::value || !std::is_same<U, DU>::value, ""); - static_assert(std::is_same<CommonType<T, U>, Expect>::value, ""); - static_assert(std::is_same<CommonType<U, T>, Expect>::value, ""); - static_assert(std::is_same<CommonType<T, U>, CommonType<DT, DU>>::value, ""); + typedef typename std::decay<T>::type DT; + typedef typename std::decay<U>::type DU; + static_assert((!std::is_same<T, DT>::value || !std::is_same<U, DU>::value), ""); + static_assert((std::is_same<typename std::common_type<T, U>::type, Expect>::value), ""); + static_assert((std::is_same<typename std::common_type<U, T>::type, Expect>::value), ""); + static_assert((std::is_same<typename std::common_type<T, U>::type, typename std::common_type<DT, DU>::type>::value), ""); } // (3.3) @@ -120,30 +133,30 @@ void test_bullet_three_one() { // Test that the user provided specialization of common_type is used after // decaying T1. { - using T1 = S<int> const; - using T2 = int; + typedef const S<int> T1; + typedef int T2; test_bullet_three_one_imp<T1, T2, S<int> >(); } // Test a user provided specialization that does not provide a typedef. { - using T1 = ::S<long> const; - using T2 = long; - static_assert(no_common_type<T1, T2>::value, ""); - static_assert(no_common_type<T2, T1>::value, ""); + typedef const ::S<long> T1; + typedef long T2; + static_assert((no_common_type<T1, T2>::value), ""); + static_assert((no_common_type<T2, T1>::value), ""); } // Test that the ternary operator is not applied when the types are the // same. { - using T1 = const void; - using Expect = void; - static_assert(std::is_same<CommonType<T1, T1>, Expect>::value, ""); - static_assert(std::is_same<CommonType<T1, T1>, CommonType<T1>>::value, ""); + typedef const void T1; + typedef void Expect; + static_assert((std::is_same<std::common_type<T1, T1>::type, Expect>::value), ""); + static_assert((std::is_same<std::common_type<T1, T1>::type, std::common_type<T1>::type>::value), ""); } { - using T1 = int const[]; - using Expect = int const*; - static_assert(std::is_same<CommonType<T1, T1>, Expect>::value, ""); - static_assert(std::is_same<CommonType<T1, T1>, CommonType<T1>>::value, ""); + typedef int const T1[]; + typedef int const* Expect; + static_assert((std::is_same<std::common_type<T1, T1>::type, Expect>::value), ""); + static_assert((std::is_same<std::common_type<T1, T1>::type, std::common_type<T1>::type>::value), ""); } } @@ -158,32 +171,32 @@ void test_bullet_three_one() { // decay_t<decltype(false ? declval<D1>() : declval<D2>())> void test_bullet_three_two() { { - using T1 = int const*; - using T2 = int*; - using Expect = TernaryOp<T1, T2>; - static_assert(std::is_same<CommonType<T1, T2>, Expect>::value, ""); - static_assert(std::is_same<CommonType<T2, T1>, Expect>::value, ""); + typedef int const* T1; + typedef int* T2; + typedef TernaryOp<T1, T2>::type Expect; + static_assert((std::is_same<std::common_type<T1, T2>::type, Expect>::value), ""); + static_assert((std::is_same<std::common_type<T2, T1>::type, Expect>::value), ""); } // Test that there is no ::type member when the ternary op is ill-formed { - using T1 = int; - using T2 = void; - static_assert(no_common_type<T1, T2>::value, ""); - static_assert(no_common_type<T2, T1>::value, ""); + typedef int T1; + typedef void T2; + static_assert((no_common_type<T1, T2>::value), ""); + static_assert((no_common_type<T2, T1>::value), ""); } { - using T1 = int; - using T2 = X<int>; - static_assert(no_common_type<T1, T2>::value, ""); - static_assert(no_common_type<T2, T1>::value, ""); + typedef int T1; + typedef X<int> T2; + static_assert((no_common_type<T1, T2>::value), ""); + static_assert((no_common_type<T2, T1>::value), ""); } // Test that the ternary operator is not applied when the types are the // same. { - using T1 = void; - using Expect = void; - static_assert(std::is_same<CommonType<T1, T1>, Expect>::value, ""); - static_assert(std::is_same<CommonType<T1, T1>, CommonType<T1>>::value, ""); + typedef void T1; + typedef void Expect; + static_assert((std::is_same<std::common_type<T1, T1>::type, Expect>::value), ""); + static_assert((std::is_same<std::common_type<T1, T1>::type, std::common_type<T1>::type>::value), ""); } } @@ -196,10 +209,12 @@ void test_bullet_three_two() { // no member type. void test_bullet_four() { { // test that there is no ::type member - static_assert(no_common_type<int, E>::value, ""); - static_assert(no_common_type<int, int, E>::value, ""); - static_assert(no_common_type<int, int, E, int>::value, ""); - static_assert(no_common_type<int, int, int, E>::value, ""); + static_assert((no_common_type<int, E>::value), ""); + static_assert((no_common_type<int, int, E>::value), ""); +#if TEST_STD_VER >= 11 + static_assert((no_common_type<int, int, E, int>::value), ""); + static_assert((no_common_type<int, int, int, E>::value), ""); +#endif } } @@ -207,8 +222,8 @@ void test_bullet_four() { // The example code specified in Note B for common_type namespace note_b_example { -using PF1 = bool (&)(); -using PF2 = short (*)(long); +typedef bool (&PF1)(); +typedef short (*PF2)(long); struct S { operator PF2() const; @@ -217,22 +232,24 @@ struct S { char data; }; -using PMF = void (S::*)(long) const; -using PMD = char S::*; +typedef void (S::*PMF)(long) const; +typedef char S::*PMD; using std::is_same; using std::result_of; using std::unique_ptr; -static_assert(is_same<typename result_of<S(int)>::type, short>::value, "Error!"); -static_assert(is_same<typename result_of<S&(unsigned char, int&)>::type, double>::value, "Error!"); -static_assert(is_same<typename result_of<PF1()>::type, bool>::value, "Error!"); -static_assert(is_same<typename result_of<PMF(unique_ptr<S>, int)>::type, void>::value, "Error!"); -static_assert(is_same<typename result_of<PMD(S)>::type, char&&>::value, "Error!"); -static_assert(is_same<typename result_of<PMD(const S*)>::type, const char&>::value, "Error!"); +static_assert((is_same<result_of<S(int)>::type, short>::value), "Error!"); +static_assert((is_same<result_of<S&(unsigned char, int&)>::type, double>::value), "Error!"); +static_assert((is_same<result_of<PF1()>::type, bool>::value), "Error!"); +static_assert((is_same<result_of<PMF(unique_ptr<S>, int)>::type, void>::value), "Error!"); +#if TEST_STD_VER >= 11 +static_assert((is_same<result_of<PMD(S)>::type, char&&>::value), "Error!"); +#endif +static_assert((is_same<result_of<PMD(const S*)>::type, const char&>::value), "Error!"); } // namespace note_b_example -#endif // TEST_STD_VER >= 11 + int main(int, char**) { @@ -286,13 +303,12 @@ int main(int, char**) static_assert((std::is_same<std::common_type<int, S<int>, S<int> >::type, S<int> >::value), ""); static_assert((std::is_same<std::common_type<int, int, S<int> >::type, S<int> >::value), ""); -#if TEST_STD_VER >= 11 + test_bullet_one(); test_bullet_two(); test_bullet_three_one(); test_bullet_three_two(); test_bullet_four(); -#endif // P0548 static_assert((std::is_same<std::common_type<S<int> >::type, S<int> >::value), ""); @@ -308,5 +324,10 @@ int main(int, char**) static_assert((std::is_same<std::common_type<int, const int>::type, int>::value), ""); static_assert((std::is_same<std::common_type<const int, const int>::type, int>::value), ""); +#if TEST_STD_VER >= 11 + // Test that we're really variadic in C++11 + static_assert(std::is_same<std::common_type<int, int, int, int, int, int, int, int>::type, int>::value, ""); +#endif + return 0; } |