forked from OSchip/llvm-project
[libc++] Make C++03 reference_wrapper more like C++11.
Remove a bunch of LIBCPP_CXX03_LANG. This is the result of a rabbithole to re-eliminate the workaround I introduced into std::cref in D117953. It turns out that Clang's C++03 mode (the only compiler we care about C++03 for) now supports all the things we were originally eschewing via LIBCPP_CXX03_LANG; we can fully support these reference_wrapper features in C++03 mode, and un-XFAIL the relevant tests. Drive-by constexprify a few more tests. Differential Revision: https://reviews.llvm.org/D117974
This commit is contained in:
parent
16031cbf2b
commit
c99a585399
|
@ -34,25 +34,16 @@ public:
|
|||
private:
|
||||
type* __f_;
|
||||
|
||||
#ifndef _LIBCPP_CXX03_LANG
|
||||
static void __fun(_Tp&) _NOEXCEPT;
|
||||
static void __fun(_Tp&&) = delete;
|
||||
#endif
|
||||
|
||||
public:
|
||||
// construct/copy/destroy
|
||||
#ifdef _LIBCPP_CXX03_LANG
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
reference_wrapper(type& __f) _NOEXCEPT
|
||||
: __f_(_VSTD::addressof(__f)) {}
|
||||
#else
|
||||
template <class _Up, class = __enable_if_t<!__is_same_uncvref<_Up, reference_wrapper>::value, decltype(__fun(declval<_Up>())) >>
|
||||
template <class _Up, class = __enable_if_t<!__is_same_uncvref<_Up, reference_wrapper>::value, decltype(__fun(declval<_Up>())) > >
|
||||
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
|
||||
reference_wrapper(_Up&& __u) _NOEXCEPT_(noexcept(__fun(declval<_Up>()))) {
|
||||
type& __f = static_cast<_Up&&>(__u);
|
||||
__f_ = _VSTD::addressof(__f);
|
||||
}
|
||||
#endif
|
||||
|
||||
// access
|
||||
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
|
||||
|
@ -210,15 +201,11 @@ inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
|
|||
reference_wrapper<const _Tp>
|
||||
cref(reference_wrapper<_Tp> __t) _NOEXCEPT
|
||||
{
|
||||
// C++20 says "return __t", but C++03 lacks the relevant
|
||||
// converting constructor. This should be equivalent.
|
||||
return __t.get();
|
||||
return __t;
|
||||
}
|
||||
|
||||
#ifndef _LIBCPP_CXX03_LANG
|
||||
template <class _Tp> void ref(const _Tp&&) = delete;
|
||||
template <class _Tp> void cref(const _Tp&&) = delete;
|
||||
#endif
|
||||
|
||||
_LIBCPP_END_NAMESPACE_STD
|
||||
|
||||
|
|
|
@ -6,8 +6,6 @@
|
|||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: c++03
|
||||
|
||||
// <functional>
|
||||
//
|
||||
// reference_wrapper
|
||||
|
@ -21,65 +19,58 @@
|
|||
#include "test_macros.h"
|
||||
|
||||
struct convertible_to_int_ref {
|
||||
int val = 0;
|
||||
operator int&() { return val; }
|
||||
operator int const&() const { return val; }
|
||||
int val = 0;
|
||||
operator int&() { return val; }
|
||||
operator int const&() const { return val; }
|
||||
};
|
||||
|
||||
template <bool IsNothrow>
|
||||
struct nothrow_convertible {
|
||||
int val = 0;
|
||||
operator int&() noexcept(IsNothrow) { return val; }
|
||||
int val = 0;
|
||||
operator int&() TEST_NOEXCEPT_COND(IsNothrow) { return val; }
|
||||
};
|
||||
|
||||
struct convertible_from_int {
|
||||
convertible_from_int(int) {}
|
||||
convertible_from_int(int) {}
|
||||
};
|
||||
|
||||
void meow(std::reference_wrapper<int>) {}
|
||||
void meow(convertible_from_int) {}
|
||||
|
||||
int gi;
|
||||
std::reference_wrapper<int> purr() { return gi; };
|
||||
|
||||
template <class T>
|
||||
void
|
||||
test(T& t)
|
||||
{
|
||||
std::reference_wrapper<T> r(t);
|
||||
assert(&r.get() == &t);
|
||||
}
|
||||
|
||||
void f() {}
|
||||
|
||||
int main(int, char**)
|
||||
{
|
||||
convertible_to_int_ref convi;
|
||||
test(convi);
|
||||
convertible_to_int_ref const convic;
|
||||
test(convic);
|
||||
|
||||
{
|
||||
{
|
||||
convertible_to_int_ref t;
|
||||
std::reference_wrapper<convertible_to_int_ref> r(t);
|
||||
assert(&r.get() == &t);
|
||||
}
|
||||
{
|
||||
const convertible_to_int_ref t;
|
||||
std::reference_wrapper<const convertible_to_int_ref> r(t);
|
||||
assert(&r.get() == &t);
|
||||
}
|
||||
{
|
||||
using Ref = std::reference_wrapper<int>;
|
||||
static_assert((std::is_nothrow_constructible<Ref, nothrow_convertible<true>>::value), "");
|
||||
static_assert((!std::is_nothrow_constructible<Ref, nothrow_convertible<false>>::value), "");
|
||||
}
|
||||
|
||||
{
|
||||
ASSERT_NOEXCEPT(Ref(nothrow_convertible<true>()));
|
||||
ASSERT_NOT_NOEXCEPT(Ref(nothrow_convertible<false>()));
|
||||
}
|
||||
{
|
||||
meow(0);
|
||||
(true) ? purr() : 0;
|
||||
}
|
||||
|
||||
#if TEST_STD_VER >= 17
|
||||
{
|
||||
}
|
||||
{
|
||||
extern std::reference_wrapper<int> purr();
|
||||
ASSERT_SAME_TYPE(decltype(true ? purr() : 0), int);
|
||||
}
|
||||
#if TEST_STD_VER > 14
|
||||
{
|
||||
int i = 0;
|
||||
std::reference_wrapper ri(i);
|
||||
static_assert((std::is_same<decltype(ri), std::reference_wrapper<int>>::value), "" );
|
||||
const int j = 0;
|
||||
std::reference_wrapper rj(j);
|
||||
static_assert((std::is_same<decltype(rj), std::reference_wrapper<const int>>::value), "" );
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -6,8 +6,6 @@
|
|||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: c++03
|
||||
|
||||
// <functional>
|
||||
//
|
||||
// reference_wrapper
|
||||
|
@ -20,46 +18,48 @@
|
|||
|
||||
#include "test_macros.h"
|
||||
|
||||
struct B {} b;
|
||||
struct B {};
|
||||
|
||||
struct A1 {
|
||||
operator B& () const { return b; }
|
||||
mutable B b_;
|
||||
TEST_CONSTEXPR operator B&() const { return b_; }
|
||||
};
|
||||
|
||||
struct A2 {
|
||||
operator B& () const noexcept { return b; }
|
||||
mutable B b_;
|
||||
TEST_CONSTEXPR operator B&() const TEST_NOEXCEPT { return b_; }
|
||||
};
|
||||
|
||||
int main(int, char**)
|
||||
void implicitly_convert(std::reference_wrapper<B>) TEST_NOEXCEPT;
|
||||
|
||||
TEST_CONSTEXPR_CXX20 bool test()
|
||||
{
|
||||
{
|
||||
std::reference_wrapper<B> b1 = A1();
|
||||
assert(&b1.get() == &b);
|
||||
b1 = A1();
|
||||
assert(&b1.get() == &b);
|
||||
|
||||
static_assert(std::is_convertible<A1, std::reference_wrapper<B>>::value, "");
|
||||
static_assert(!std::is_nothrow_constructible<std::reference_wrapper<B>, A1>::value, "");
|
||||
#if TEST_STD_VER >= 20
|
||||
static_assert(!std::is_nothrow_convertible_v<A1, std::reference_wrapper<B>>);
|
||||
#endif
|
||||
static_assert(std::is_assignable<std::reference_wrapper<B>, A1>::value, "");
|
||||
static_assert(!std::is_nothrow_assignable<std::reference_wrapper<B>, A1>::value, "");
|
||||
}
|
||||
|
||||
{
|
||||
std::reference_wrapper<B> b2 = A2();
|
||||
assert(&b2.get() == &b);
|
||||
b2 = A2();
|
||||
assert(&b2.get() == &b);
|
||||
|
||||
static_assert(std::is_convertible<A2, std::reference_wrapper<B>>::value, "");
|
||||
static_assert(std::is_nothrow_constructible<std::reference_wrapper<B>, A2>::value, "");
|
||||
#if TEST_STD_VER >= 20
|
||||
static_assert(std::is_nothrow_convertible_v<A2, std::reference_wrapper<B>>);
|
||||
#endif
|
||||
static_assert(std::is_assignable<std::reference_wrapper<B>, A2>::value, "");
|
||||
static_assert(std::is_nothrow_assignable<std::reference_wrapper<B>, A2>::value, "");
|
||||
}
|
||||
|
||||
return 0;
|
||||
{
|
||||
A1 a;
|
||||
ASSERT_NOT_NOEXCEPT(implicitly_convert(a));
|
||||
std::reference_wrapper<B> b1 = a;
|
||||
assert(&b1.get() == &a.b_);
|
||||
ASSERT_NOT_NOEXCEPT(b1 = a);
|
||||
b1 = a;
|
||||
assert(&b1.get() == &a.b_);
|
||||
}
|
||||
{
|
||||
A2 a;
|
||||
ASSERT_NOEXCEPT(implicitly_convert(a));
|
||||
std::reference_wrapper<B> b2 = a;
|
||||
assert(&b2.get() == &a.b_);
|
||||
ASSERT_NOEXCEPT(b2 = a);
|
||||
b2 = a;
|
||||
assert(&b2.get() == &a.b_);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
int main(int, char**) {
|
||||
test();
|
||||
#if TEST_STD_VER > 17
|
||||
static_assert(test());
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -12,8 +12,6 @@
|
|||
|
||||
// reference_wrapper(T&&) = delete;
|
||||
|
||||
// XFAIL: c++03
|
||||
|
||||
#include <functional>
|
||||
#include <cassert>
|
||||
|
||||
|
|
|
@ -14,8 +14,6 @@
|
|||
|
||||
// Don't allow binding to a temp
|
||||
|
||||
// XFAIL: c++03
|
||||
|
||||
#include <functional>
|
||||
|
||||
struct A {};
|
||||
|
|
Loading…
Reference in New Issue