Last active
June 28, 2017 23:37
-
-
Save ericniebler/7cff48607b44a949f5cc7e86ff17cecf to your computer and use it in GitHub Desktop.
reference_wrapper minus the nasty implicit conversion sequence from rvalues
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <type_traits> | |
#include <functional> | |
template <class T, class...As> | |
concept bool Constructible = | |
std::is_constructible_v<T, As...>; | |
template <class A, class B> | |
concept bool Same = __is_same_as(A, B); | |
template <class T1, class T2> | |
concept bool __cv_greater_equal = | |
(std::is_const_v<T1> || !std::is_const_v<T2>) && | |
(std::is_volatile_v<T1> || !std::is_volatile_v<T2>); | |
struct A {}; | |
struct B : A {}; | |
template <class T1, class T2> | |
concept bool _ReferenceCompatible = | |
(Same<std::remove_cv_t<T1>, std::remove_cv_t<T2>> || std::is_base_of_v<T1, T2>) && | |
__cv_greater_equal<T1, T2>; | |
static_assert(_ReferenceCompatible<int const, int>); | |
static_assert(_ReferenceCompatible<A const, B>); | |
template <class T> | |
struct _LvalueRef { | |
_LvalueRef(T&); | |
_LvalueRef(T&&) = delete; | |
}; | |
template <class T> | |
struct reference_wrapper; | |
template <class U, class T> | |
concept bool _ReferenceWrapperCompatible = | |
Constructible<_LvalueRef<T>, U> && | |
!Same<std::decay_t<U>, reference_wrapper<T>>; | |
template <class U, class T> | |
concept bool _LvalueReferenceWrapperCompatible = | |
_ReferenceWrapperCompatible<U, T> && | |
std::is_lvalue_reference_v<U> && | |
_ReferenceCompatible<T, std::remove_reference_t<U>>; | |
template <class T> | |
struct reference_wrapper { | |
explicit reference_wrapper(_ReferenceWrapperCompatible<T> &&); | |
reference_wrapper(_LvalueReferenceWrapperCompatible<T> &&); | |
operator T& () const noexcept; | |
}; | |
using T = std::common_type_t<reference_wrapper<int>, int>; | |
static_assert(std::is_constructible<reference_wrapper<int>, int&>::value, ""); | |
static_assert(std::is_constructible<reference_wrapper<int const>, int const&>::value, ""); | |
static_assert(!std::is_constructible<reference_wrapper<int>, int>::value, ""); | |
static_assert(!std::is_constructible<reference_wrapper<int const>, int const>::value, ""); | |
// Proxy references | |
struct ProxyInt { | |
operator int&() const; | |
}; | |
static_assert(std::is_constructible<reference_wrapper<int>, ProxyInt>::value, ""); | |
static_assert(std::is_constructible<std::reference_wrapper<int>, ProxyInt>::value, ""); | |
static_assert(!std::is_convertible<reference_wrapper<int>, reference_wrapper<int const>>::value, ""); | |
static_assert(!std::is_convertible<std::reference_wrapper<int>, std::reference_wrapper<int const>>::value, ""); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment