summaryrefslogtreecommitdiffstats
path: root/libcxx/test/std/utilities/meta
diff options
context:
space:
mode:
authorEric Fiselier <eric@efcs.ca>2019-03-31 20:49:06 +0000
committerEric Fiselier <eric@efcs.ca>2019-03-31 20:49:06 +0000
commitb0e79823d699d9a0c65edb7f425d55a305cccde3 (patch)
tree9a86a30e2643f9516095b89bbbae930baa13f5c3 /libcxx/test/std/utilities/meta
parent76829d8928790d573e0bdc2dc1a2f042ecb8eeaa (diff)
downloadbcm5719-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.cpp175
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;
}
OpenPOWER on IntegriCloud