Skip to content

Instantly share code, notes, and snippets.

@ericniebler
Last active June 28, 2017 23:37
Show Gist options
  • Save ericniebler/7cff48607b44a949f5cc7e86ff17cecf to your computer and use it in GitHub Desktop.
Save ericniebler/7cff48607b44a949f5cc7e86ff17cecf to your computer and use it in GitHub Desktop.
reference_wrapper minus the nasty implicit conversion sequence from rvalues
#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