Bug 16599 part 2: Make std::pair's constructors and comparison operators (and make_pair) constexpr.

git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@186430 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Marshall Clow 2013-07-16 17:45:44 +00:00
parent 01a0e90783
commit 206f6cdc33
8 changed files with 135 additions and 30 deletions

@ -66,10 +66,10 @@ struct pair
pair(const pair&) = default; pair(const pair&) = default;
pair(pair&&) = default; pair(pair&&) = default;
constexpr pair(); constexpr pair();
pair(const T1& x, const T2& y); pair(const T1& x, const T2& y); // constexpr in C++14
template <class U, class V> pair(U&& x, V&& y); template <class U, class V> pair(U&& x, V&& y); // constexpr in C++14
template <class U, class V> pair(const pair<U, V>& p); template <class U, class V> pair(const pair<U, V>& p); // constexpr in C++14
template <class U, class V> pair(pair<U, V>&& p); template <class U, class V> pair(pair<U, V>&& p); // constexpr in C++14
template <class... Args1, class... Args2> template <class... Args1, class... Args2>
pair(piecewise_construct_t, tuple<Args1...> first_args, pair(piecewise_construct_t, tuple<Args1...> first_args,
tuple<Args2...> second_args); tuple<Args2...> second_args);
@ -83,14 +83,14 @@ struct pair
noexcept(swap(second, p.second))); noexcept(swap(second, p.second)));
}; };
template <class T1, class T2> bool operator==(const pair<T1,T2>&, const pair<T1,T2>&); template <class T1, class T2> bool operator==(const pair<T1,T2>&, const pair<T1,T2>&); // constexpr in C++14
template <class T1, class T2> bool operator!=(const pair<T1,T2>&, const pair<T1,T2>&); template <class T1, class T2> bool operator!=(const pair<T1,T2>&, const pair<T1,T2>&); // constexpr in C++14
template <class T1, class T2> bool operator< (const pair<T1,T2>&, const pair<T1,T2>&); template <class T1, class T2> bool operator< (const pair<T1,T2>&, const pair<T1,T2>&); // constexpr in C++14
template <class T1, class T2> bool operator> (const pair<T1,T2>&, const pair<T1,T2>&); template <class T1, class T2> bool operator> (const pair<T1,T2>&, const pair<T1,T2>&); // constexpr in C++14
template <class T1, class T2> bool operator>=(const pair<T1,T2>&, const pair<T1,T2>&); template <class T1, class T2> bool operator>=(const pair<T1,T2>&, const pair<T1,T2>&); // constexpr in C++14
template <class T1, class T2> bool operator<=(const pair<T1,T2>&, const pair<T1,T2>&); template <class T1, class T2> bool operator<=(const pair<T1,T2>&, const pair<T1,T2>&); // constexpr in C++14
template <class T1, class T2> pair<V1, V2> make_pair(T1&&, T2&&); template <class T1, class T2> pair<V1, V2> make_pair(T1&&, T2&&); // constexpr in C++14
template <class T1, class T2> template <class T1, class T2>
void void
swap(pair<T1, T2>& x, pair<T1, T2>& y) noexcept(noexcept(x.swap(y))); swap(pair<T1, T2>& x, pair<T1, T2>& y) noexcept(noexcept(x.swap(y)));
@ -258,11 +258,12 @@ struct _LIBCPP_TYPE_VIS pair
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR pair() : first(), second() {} _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR pair() : first(), second() {}
_LIBCPP_INLINE_VISIBILITY pair(const _T1& __x, const _T2& __y) _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11
pair(const _T1& __x, const _T2& __y)
: first(__x), second(__y) {} : first(__x), second(__y) {}
template<class _U1, class _U2> template<class _U1, class _U2>
_LIBCPP_INLINE_VISIBILITY _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11
pair(const pair<_U1, _U2>& __p pair(const pair<_U1, _U2>& __p
#ifndef _LIBCPP_HAS_NO_ADVANCED_SFINAE #ifndef _LIBCPP_HAS_NO_ADVANCED_SFINAE
,typename enable_if<is_convertible<const _U1&, _T1>::value && ,typename enable_if<is_convertible<const _U1&, _T1>::value &&
@ -271,6 +272,10 @@ struct _LIBCPP_TYPE_VIS pair
) )
: first(__p.first), second(__p.second) {} : first(__p.first), second(__p.second) {}
#ifndef _LIBCPP_HAS_NO_DEFAULTED_FUNCTIONS
_LIBCPP_INLINE_VISIBILITY
pair(const pair& __p) = default;
#else
_LIBCPP_INLINE_VISIBILITY _LIBCPP_INLINE_VISIBILITY
pair(const pair& __p) pair(const pair& __p)
_NOEXCEPT_(is_nothrow_copy_constructible<first_type>::value && _NOEXCEPT_(is_nothrow_copy_constructible<first_type>::value &&
@ -279,6 +284,7 @@ struct _LIBCPP_TYPE_VIS pair
second(__p.second) second(__p.second)
{ {
} }
#endif
_LIBCPP_INLINE_VISIBILITY _LIBCPP_INLINE_VISIBILITY
pair& operator=(const pair& __p) pair& operator=(const pair& __p)
@ -295,20 +301,24 @@ struct _LIBCPP_TYPE_VIS pair
template <class _U1, class _U2, template <class _U1, class _U2,
class = typename enable_if<is_convertible<_U1, first_type>::value && class = typename enable_if<is_convertible<_U1, first_type>::value &&
is_convertible<_U2, second_type>::value>::type> is_convertible<_U2, second_type>::value>::type>
_LIBCPP_INLINE_VISIBILITY _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11
pair(_U1&& __u1, _U2&& __u2) pair(_U1&& __u1, _U2&& __u2)
: first(_VSTD::forward<_U1>(__u1)), : first(_VSTD::forward<_U1>(__u1)),
second(_VSTD::forward<_U2>(__u2)) second(_VSTD::forward<_U2>(__u2))
{} {}
template<class _U1, class _U2> template<class _U1, class _U2>
_LIBCPP_INLINE_VISIBILITY _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11
pair(pair<_U1, _U2>&& __p, pair(pair<_U1, _U2>&& __p,
typename enable_if<is_convertible<_U1, _T1>::value && typename enable_if<is_convertible<_U1, _T1>::value &&
is_convertible<_U2, _T2>::value>::type* = 0) is_convertible<_U2, _T2>::value>::type* = 0)
: first(_VSTD::forward<_U1>(__p.first)), : first(_VSTD::forward<_U1>(__p.first)),
second(_VSTD::forward<_U2>(__p.second)) {} second(_VSTD::forward<_U2>(__p.second)) {}
#ifndef _LIBCPP_HAS_NO_DEFAULTED_FUNCTIONS
_LIBCPP_INLINE_VISIBILITY
pair(pair&& __p) = default;
#else
_LIBCPP_INLINE_VISIBILITY _LIBCPP_INLINE_VISIBILITY
pair(pair&& __p) _NOEXCEPT_(is_nothrow_move_constructible<first_type>::value && pair(pair&& __p) _NOEXCEPT_(is_nothrow_move_constructible<first_type>::value &&
is_nothrow_move_constructible<second_type>::value) is_nothrow_move_constructible<second_type>::value)
@ -316,6 +326,7 @@ struct _LIBCPP_TYPE_VIS pair
second(_VSTD::forward<second_type>(__p.second)) second(_VSTD::forward<second_type>(__p.second))
{ {
} }
#endif
_LIBCPP_INLINE_VISIBILITY _LIBCPP_INLINE_VISIBILITY
pair& pair&
@ -331,7 +342,7 @@ struct _LIBCPP_TYPE_VIS pair
template<class _Tuple, template<class _Tuple,
class = typename enable_if<__tuple_convertible<_Tuple, pair>::value>::type> class = typename enable_if<__tuple_convertible<_Tuple, pair>::value>::type>
_LIBCPP_INLINE_VISIBILITY _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11
pair(_Tuple&& __p) pair(_Tuple&& __p)
: first(_VSTD::forward<typename tuple_element<0, : first(_VSTD::forward<typename tuple_element<0,
typename __make_tuple_types<_Tuple>::type>::type>(get<0>(__p))), typename __make_tuple_types<_Tuple>::type>::type>(get<0>(__p))),
@ -387,7 +398,7 @@ private:
}; };
template <class _T1, class _T2> template <class _T1, class _T2>
inline _LIBCPP_INLINE_VISIBILITY inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11
bool bool
operator==(const pair<_T1,_T2>& __x, const pair<_T1,_T2>& __y) operator==(const pair<_T1,_T2>& __x, const pair<_T1,_T2>& __y)
{ {
@ -395,7 +406,7 @@ operator==(const pair<_T1,_T2>& __x, const pair<_T1,_T2>& __y)
} }
template <class _T1, class _T2> template <class _T1, class _T2>
inline _LIBCPP_INLINE_VISIBILITY inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11
bool bool
operator!=(const pair<_T1,_T2>& __x, const pair<_T1,_T2>& __y) operator!=(const pair<_T1,_T2>& __x, const pair<_T1,_T2>& __y)
{ {
@ -403,7 +414,7 @@ operator!=(const pair<_T1,_T2>& __x, const pair<_T1,_T2>& __y)
} }
template <class _T1, class _T2> template <class _T1, class _T2>
inline _LIBCPP_INLINE_VISIBILITY inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11
bool bool
operator< (const pair<_T1,_T2>& __x, const pair<_T1,_T2>& __y) operator< (const pair<_T1,_T2>& __x, const pair<_T1,_T2>& __y)
{ {
@ -411,7 +422,7 @@ operator< (const pair<_T1,_T2>& __x, const pair<_T1,_T2>& __y)
} }
template <class _T1, class _T2> template <class _T1, class _T2>
inline _LIBCPP_INLINE_VISIBILITY inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11
bool bool
operator> (const pair<_T1,_T2>& __x, const pair<_T1,_T2>& __y) operator> (const pair<_T1,_T2>& __x, const pair<_T1,_T2>& __y)
{ {
@ -419,7 +430,7 @@ operator> (const pair<_T1,_T2>& __x, const pair<_T1,_T2>& __y)
} }
template <class _T1, class _T2> template <class _T1, class _T2>
inline _LIBCPP_INLINE_VISIBILITY inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11
bool bool
operator>=(const pair<_T1,_T2>& __x, const pair<_T1,_T2>& __y) operator>=(const pair<_T1,_T2>& __x, const pair<_T1,_T2>& __y)
{ {
@ -427,7 +438,7 @@ operator>=(const pair<_T1,_T2>& __x, const pair<_T1,_T2>& __y)
} }
template <class _T1, class _T2> template <class _T1, class _T2>
inline _LIBCPP_INLINE_VISIBILITY inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11
bool bool
operator<=(const pair<_T1,_T2>& __x, const pair<_T1,_T2>& __y) operator<=(const pair<_T1,_T2>& __x, const pair<_T1,_T2>& __y)
{ {
@ -472,7 +483,7 @@ struct __make_pair_return
}; };
template <class _T1, class _T2> template <class _T1, class _T2>
inline _LIBCPP_INLINE_VISIBILITY inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11
pair<typename __make_pair_return<_T1>::type, typename __make_pair_return<_T2>::type> pair<typename __make_pair_return<_T1>::type, typename __make_pair_return<_T2>::type>
make_pair(_T1&& __t1, _T2&& __t2) make_pair(_T1&& __t1, _T2&& __t2)
{ {
@ -615,42 +626,42 @@ template <class _T1, class _T2>
_LIBCPP_INLINE_VISIBILITY inline _LIBCPP_INLINE_VISIBILITY inline
constexpr _T1 & get(pair<_T1, _T2>& __p) _NOEXCEPT constexpr _T1 & get(pair<_T1, _T2>& __p) _NOEXCEPT
{ {
return __get_pair<0>::get(__p); return __get_pair<0>::get(__p);
} }
template <class _T1, class _T2> template <class _T1, class _T2>
_LIBCPP_INLINE_VISIBILITY inline _LIBCPP_INLINE_VISIBILITY inline
constexpr _T1 const & get(pair<_T1, _T2> const& __p) _NOEXCEPT constexpr _T1 const & get(pair<_T1, _T2> const& __p) _NOEXCEPT
{ {
return __get_pair<0>::get(__p); return __get_pair<0>::get(__p);
} }
template <class _T1, class _T2> template <class _T1, class _T2>
_LIBCPP_INLINE_VISIBILITY inline _LIBCPP_INLINE_VISIBILITY inline
constexpr _T1 && get(pair<_T1, _T2>&& __p) _NOEXCEPT constexpr _T1 && get(pair<_T1, _T2>&& __p) _NOEXCEPT
{ {
return __get_pair<0>::get(_VSTD::move(__p)); return __get_pair<0>::get(_VSTD::move(__p));
} }
template <class _T1, class _T2> template <class _T1, class _T2>
_LIBCPP_INLINE_VISIBILITY inline _LIBCPP_INLINE_VISIBILITY inline
constexpr _T1 & get(pair<_T2, _T1>& __p) _NOEXCEPT constexpr _T1 & get(pair<_T2, _T1>& __p) _NOEXCEPT
{ {
return __get_pair<1>::get(__p); return __get_pair<1>::get(__p);
} }
template <class _T1, class _T2> template <class _T1, class _T2>
_LIBCPP_INLINE_VISIBILITY inline _LIBCPP_INLINE_VISIBILITY inline
constexpr _T1 const & get(pair<_T2, _T1> const& __p) _NOEXCEPT constexpr _T1 const & get(pair<_T2, _T1> const& __p) _NOEXCEPT
{ {
return __get_pair<1>::get(__p); return __get_pair<1>::get(__p);
} }
template <class _T1, class _T2> template <class _T1, class _T2>
_LIBCPP_INLINE_VISIBILITY inline _LIBCPP_INLINE_VISIBILITY inline
constexpr _T1 && get(pair<_T2, _T1>&& __p) _NOEXCEPT constexpr _T1 && get(pair<_T2, _T1>&& __p) _NOEXCEPT
{ {
return __get_pair<1>::get(_VSTD::move(__p)); return __get_pair<1>::get(_VSTD::move(__p));
} }
#endif #endif

@ -26,4 +26,15 @@ int main()
assert(std::get<0>(p) == 3); assert(std::get<0>(p) == 3);
assert(std::get<1>(p) == 4); assert(std::get<1>(p) == 4);
} }
#if __cplusplus > 201103L
{
typedef std::pair<int, short> P;
constexpr P p1(3, 4);
static_assert(p1.first == 3, "" ); // for now!
static_assert(p1.second == 4, "" ); // for now!
// static_assert(std::get<0>(p1) == 3, "");
// static_assert(std::get<1>(p1) == 4, "");
}
#endif
} }

@ -22,9 +22,20 @@ class A
public: public:
A(int data) : data_(data) {} A(int data) : data_(data) {}
bool operator==(const A& a) {return data_ == a.data_;} bool operator==(const A& a) const {return data_ == a.data_;}
}; };
#if _LIBCPP_STD_VER > 11
class AC
{
int data_;
public:
constexpr AC(int data) : data_(data) {}
constexpr bool operator==(const AC& a) const {return data_ == a.data_;}
};
#endif
int main() int main()
{ {
{ {
@ -39,4 +50,19 @@ int main()
assert(p.first == A(1)); assert(p.first == A(1));
assert(p.second == 2); assert(p.second == 2);
} }
#if _LIBCPP_STD_VER > 11
{
typedef std::pair<float, short*> P;
constexpr P p(3.5f, 0);
static_assert(p.first == 3.5f, "");
static_assert(p.second == nullptr, "");
}
{
typedef std::pair<AC, int> P;
constexpr P p(1, 2);
static_assert(p.first == AC(1), "");
static_assert(p.second == 2, "");
}
#endif
} }

@ -26,4 +26,15 @@ int main()
assert(p2.first == 3); assert(p2.first == 3);
assert(p2.second == 4); assert(p2.second == 4);
} }
#if _LIBCPP_STD_VER > 11
{
typedef std::pair<int, short> P1;
typedef std::pair<double, long> P2;
constexpr P1 p1(3, 4);
constexpr P2 p2 = p1;
static_assert(p2.first == 3, "");
static_assert(p2.second == 4, "");
}
#endif
} }

@ -25,4 +25,14 @@ int main()
assert(p2.first == 3); assert(p2.first == 3);
assert(p2.second == 4); assert(p2.second == 4);
} }
#if _LIBCPP_STD_VER > 11
{
typedef std::pair<int, short> P1;
constexpr P1 p1(3, 4);
constexpr P1 p2 = p1;
static_assert(p2.first == 3, "");
static_assert(p2.second == 4, "");
}
#endif
} }

@ -18,8 +18,19 @@
int main() int main()
{ {
{
typedef std::pair<float, short*> P; typedef std::pair<float, short*> P;
P p; P p;
assert(p.first == 0.0f); assert(p.first == 0.0f);
assert(p.second == nullptr); assert(p.second == nullptr);
}
#if _LIBCPP_STD_VER > 11
{
typedef std::pair<float, short*> P;
constexpr P p;
static_assert(p.first == 0.0f, "");
static_assert(p.second == nullptr, "");
}
#endif
} }

@ -78,4 +78,18 @@ int main()
assert( (p1 > p2)); assert( (p1 > p2));
assert( (p1 >= p2)); assert( (p1 >= p2));
} }
#if _LIBCPP_STD_VER > 11
{
typedef std::pair<int, short> P;
constexpr P p1(3, 4);
constexpr P p2(3, 2);
static_assert(!(p1 == p2), "");
static_assert( (p1 != p2), "");
static_assert(!(p1 < p2), "");
static_assert(!(p1 <= p2), "");
static_assert( (p1 > p2), "");
static_assert( (p1 >= p2), "");
}
#endif
} }

@ -23,6 +23,7 @@ int main()
assert(p1.first == 3); assert(p1.first == 3);
assert(p1.second == 4); assert(p1.second == 4);
} }
#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES #ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
{ {
typedef std::pair<std::unique_ptr<int>, short> P1; typedef std::pair<std::unique_ptr<int>, short> P1;
@ -37,4 +38,14 @@ int main()
assert(p1.second == 4); assert(p1.second == 4);
} }
#endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES #endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES
#if _LIBCPP_STD_VER > 11
{
typedef std::pair<int, short> P1;
constexpr P1 p1 = std::make_pair(3, 4);
static_assert(p1.first == 3, "");
static_assert(p1.second == 4, "");
}
#endif
} }