_M_reset(__ptr);
if constexpr (__pocma)
- _M_alloc = __other._M_alloc;
+ _M_alloc = std::move(__other._M_alloc);
return *this;
}
_M_reset(__ptr);
if constexpr (__pocma)
- _M_alloc = __other._M_alloc;
+ _M_alloc = std::move(__other._M_alloc);
return *this;
}
using Indirect = std::indirect<Vector, tracker_allocator<Vector>>;
const Indirect src(std::in_place, {1, 2, 3});
-constexpr void
+void
test_ctor()
{
Counter::reset();
VERIFY( Counter::get_destruct_count() == 0 );
}
-constexpr void
+void
test_assign()
{
Indirect i1;
VERIFY( Counter::get_destruct_count() == 0 );
}
-constexpr void
+void
test_valueless()
{
Indirect e;
}
constexpr void
-test_all()
+test_constexpr()
{
- test_ctor();
- test_assign();
- test_valueless();
+ using Alloc = __gnu_test::uneq_allocator<Vector>;
+ using Indirect = std::indirect<Vector, Alloc>;
+ const Indirect src(std::in_place, {1, 2, 3});
+
+ Indirect i1(src);
+ VERIFY( *i1 == *src );
+ VERIFY( &*i1 != &*src );
+ VERIFY( i1.get_allocator() == Alloc{} );
+
+ Indirect i2(std::allocator_arg, Alloc{2}, src);
+ VERIFY( *i2 == *src );
+ VERIFY( &*i2 != &*src );
+ VERIFY( i2.get_allocator() == Alloc{2} );
+
+ Indirect i3(std::allocator_arg, Alloc{3});
+ i3 = src;
+ VERIFY( *i3 == *src );
+ VERIFY( &*i3 != &*src );
+ VERIFY( i3.get_allocator() == Alloc{3} );
+
+ Indirect e;
+ auto(std::move(e));
+ VERIFY( e.valueless_after_move() );
+
+ Indirect e1(e);
+ VERIFY( e1.valueless_after_move() );
+
+ Indirect e2(std::allocator_arg, {}, e);
+ VERIFY( e2.valueless_after_move() );
+
+ i3 = e;
+ VERIFY( i3.valueless_after_move() );
+
+ i3 = e;
+ VERIFY( i3.valueless_after_move() );
}
int main()
{
- test_all();
+ test_ctor();
+ test_assign();
+ test_valueless();
+ test_constexpr();
static_assert([] {
- test_all();
+ test_constexpr();
return true;
- });
+ }());
}
using Counter = __gnu_test::tracker_allocator_counter;
template<bool Propagate>
-constexpr void
+void
test_ctor()
{
using PropAlloc = propagating_allocator<int, Propagate>;
}
template<bool Propagate>
-constexpr void
+void
test_assign()
{
using PropAlloc = propagating_allocator<int, Propagate>;
}
template<bool Propagate>
-constexpr void
+void
test_valueless()
{
using PropAlloc = propagating_allocator<int, Propagate>;
{
test_all<true>();
test_all<false>();
-
- static_assert([] {
- test_all<true>();
- test_all<false>();
- return true;
- });
}
std::indirect<Obj, default_init_allocator<Obj>> i2(std::allocator_arg, a);
VERIFY( i2.get_allocator() == a );
+ if (std::is_constant_evaluated())
+ return;
+
// Object is constructed using allocator-aware constructor.
std::indirect<std::vector<int, UneqAlloc>, ScopedAlloc>
i3(std::allocator_arg, ScopedAlloc(11, 22));
std::indirect<Obj> i6(7);
VERIFY( i6->i == 7 );
+ if (std::is_constant_evaluated())
+ return;
+
std::vector<int, UneqAlloc> v{1, 2, 3, 4, 5};
// Object is constructed using allocator-aware constructor.
std::indirect<std::vector<int, UneqAlloc>, ScopedAlloc>
VERIFY( i10->at(2) == 3 );
VERIFY( i10->get_allocator().get_personality() == 42 );
+ if (std::is_constant_evaluated())
+ return;
+
std::indirect<std::vector<int, UneqAlloc>, ScopedAlloc>
i14(std::allocator_arg, ScopedAlloc(11, 22),
std::in_place);
test_forwarding_ctor();
test_inplace_ctor();
return true;
- });
+ }());
}
using Indirect = std::indirect<Vector, tracker_allocator<Vector>>;
const Indirect val(std::in_place, {1, 2, 3});
-constexpr void
+void
verifyNoAllocations()
{
VERIFY( Counter::get_allocation_count() == 0 );
VERIFY( Counter::get_destruct_count() == 0 );
}
-constexpr void
+void
test_ctor()
{
std::optional<Indirect> src;
verifyNoAllocations();
}
-constexpr void
+void
test_assign()
{
std::optional<Indirect> src;
verifyNoAllocations();
}
-constexpr void
+void
test_swap()
{
const Indirect val1(std::in_place, {1, 2, 3});
verifyNoAllocations();
auto(std::move(i1));
-
+
Counter::reset();
i1.swap(i2);
VERIFY( *i1 == *val1 );
verifyNoAllocations();
}
-constexpr void
+void
test_valueless()
{
auto e = [] {
}
constexpr void
-test_all()
+test_constexpr()
{
- test_ctor();
- test_assign();
- test_swap();
- test_valueless();
+ using Alloc = __gnu_test::uneq_allocator<Vector>;
+ using Indirect = std::indirect<Vector, Alloc>;
+ const Indirect val(std::in_place, {1, 2, 3});
+
+ std::optional<Indirect> src;
+ auto make = [&src, &val] -> Indirect&& {
+ src.emplace(val);
+ return std::move(*src);
+ };
+
+ Indirect i1(make());
+ VERIFY( src->valueless_after_move() );
+ VERIFY( *i1 == *val );
+
+ Indirect i2(std::allocator_arg, {}, make());
+ VERIFY( src->valueless_after_move() );
+ VERIFY( *i2 == *val );
+
+ i2 = make();
+ VERIFY( src->valueless_after_move() );
+ VERIFY( *i2 == *val );
+
+ auto(std::move(i2));
+ i2 = make();
+ VERIFY( *i2 == *val );
+ VERIFY( src->valueless_after_move() );
+
+ const Indirect val1(std::in_place, {1, 2, 3});
+ const Indirect val2(std::in_place, {2, 4, 6});
+
+ Indirect s1(val1);
+ Indirect s2(val2);
+ s1.swap(s2);
+ VERIFY( *s2 == *val1 );
+ VERIFY( *s1 == *val2 );
+
+ auto(std::move(s1));
+
+ s1.swap(s2);
+ VERIFY( *s1 == *val1 );
+ VERIFY( s2.valueless_after_move() );
+
+ auto e = [] {
+ Indirect res;
+ auto(std::move(res));
+ return res;
+ };
+
+ Indirect e1(e());
+ VERIFY( e1.valueless_after_move() );
+
+ Indirect e2(std::allocator_arg, {}, e());
+ VERIFY( e2.valueless_after_move() );
+
+ Indirect e3(val);
+ e3 = e();
+ e3 = e();
}
int main()
{
- test_all();
+ test_ctor();
+ test_assign();
+ test_swap();
+ test_valueless();
+ test_constexpr();
static_assert([] {
- test_all();
+ test_constexpr();
return true;
- });
+ }());
}
using __gnu_test::tracker_allocator;
using Counter = __gnu_test::tracker_allocator_counter;
-constexpr void
+void
verifyNoAllocations()
{
VERIFY( Counter::get_allocation_count() == 0 );
}
template<bool Propagate>
-constexpr void
+void
test_ctor()
{
using PropAlloc = propagating_allocator<int, Propagate>;
}
template<bool Propagate>
-constexpr void
+void
test_assign()
{
using PropAlloc = propagating_allocator<int, Propagate>;
}
template<bool Propagate>
-constexpr void
+void
test_swap()
{
using PropAlloc = propagating_allocator<int, Propagate>;
}
template<bool Propagate>
-constexpr void
+void
test_valueless()
{
using PropAlloc = propagating_allocator<int, Propagate>;
}
template<bool Propagate>
-constexpr void
+void
test_all()
{
test_ctor<Propagate>();
{
test_all<true>();
test_all<false>();
-
- static_assert([] {
- test_all<true>();
- test_all<false>();
- return true;
- });
}
test_relops();
test_comp_with_t();
return true;
- });
+ }());
}
using Polymorphic = std::polymorphic<Base, tracker_allocator<Base>>;
const Polymorphic src(std::in_place_type<Derived>, 1, 2, 3);
-constexpr void
+void
test_ctor()
{
Counter::reset();
VERIFY( Counter::get_destruct_count() == 0 );
}
-constexpr void
+void
test_assign()
{
Counter::reset();
VERIFY( Counter::get_destruct_count() == 0 );
}
-constexpr void
+void
test_valueless()
{
Polymorphic e(std::in_place_type<Derived>);
}
constexpr void
-test_all()
+test_constexpr()
{
- test_ctor();
- test_assign();
- test_valueless();
+ using Polymorphic = std::polymorphic<Base, __gnu_test::uneq_allocator<Base>>;
+ const Polymorphic src(std::in_place_type<Derived>, 1, 2, 3);
+
+ Polymorphic i1(src);
+ VERIFY( *i1 == *src );
+ VERIFY( &*i1 != &*src );
+
+ Polymorphic i2(std::allocator_arg, {}, src);
+ VERIFY( *i2 == *src );
+ VERIFY( &*i2 != &*src );
+
+ i1 = Polymorphic(std::in_place_type<Derived>);
+ VERIFY( *i1 != *src );
+ i1 = src;
+ VERIFY( *i1 == *src );
+ VERIFY( &*i1 != &*src );
+
+ auto(std::move(i1));
+ i1 = src;
+ VERIFY( *i1 == *src );
+ VERIFY( &*i1 != &*src );
+
+ Polymorphic e(std::in_place_type<Derived>);
+ auto(std::move(e));
+ VERIFY( e.valueless_after_move() );
+
+ Polymorphic e1(e);
+ VERIFY( e1.valueless_after_move() );
+
+ Polymorphic e2(std::allocator_arg, {}, e);
+ VERIFY( e2.valueless_after_move() );
+
+ Polymorphic e3(src);
+ e3 = e;
+ VERIFY( e3.valueless_after_move() );
}
int main()
{
- test_all();
+ test_ctor();
+ test_assign();
+ test_valueless();
+ test_constexpr();
static_assert([] {
- test_all();
+ test_constexpr();
return true;
- });
+ }());
}
#include <testsuite_allocator.h>
struct Base {
- friend constexpr
+ friend
bool operator==(const Base& lhs, const Base& rhs)
{ return lhs.eq(rhs); }
- virtual constexpr int
+ virtual int
get_alloc_personality() const
{ return -1; }
private:
- constexpr virtual bool
+ virtual bool
eq(const Base& other) const = 0;
};
using VecBase::VecBase;
- constexpr int
+ int
get_alloc_personality() const override
{ return this->get_allocator().get_personality(); }
private:
- constexpr bool
+ bool
eq(const Base& other) const override
{
if (auto op = dynamic_cast<const VecDerived*>(&other))
using Counter = __gnu_test::tracker_allocator_counter;
template<bool Propagate>
-constexpr void
+void
test_ctor()
{
using PropAlloc = propagating_allocator<int, Propagate>;
}
template<bool Propagate>
-constexpr void
+void
test_assign()
{
using PropAlloc = propagating_allocator<int, Propagate>;
}
template<bool Propagate>
-constexpr void
+void
test_valueless()
{
using PropAlloc = propagating_allocator<int, Propagate>;
}
template<bool Propagate>
-constexpr void
+void
test_all()
{
test_ctor<Propagate>();
{
test_all<true>();
test_all<false>();
-
- static_assert([] {
- test_all<true>();
- test_all<false>();
- return true;
- });
}
std::polymorphic<Obj, default_init_allocator<Obj>> i2(std::allocator_arg, a);
VERIFY( i2.get_allocator() == a );
+ if (std::is_constant_evaluated())
+ return;
+
// Object is constructed using allocator-aware constructor.
std::polymorphic<std::vector<int, UneqAlloc>, ScopedAlloc>
i3(std::allocator_arg, ScopedAlloc(11, 22));
std::polymorphic<Obj> i5({1, {'2', '3'}});
verify(i5);
+ if (std::is_constant_evaluated())
+ return;
+
std::vector<int, UneqAlloc> v{1, 2, 3, 4, 5};
// Object is constructed using allocator-aware constructor.
std::polymorphic<std::vector<int, UneqAlloc>, ScopedAlloc>
VERIFY( i10->at(2) == 3 );
VERIFY( i10->get_allocator().get_personality() == 42 );
+ if (std::is_constant_evaluated())
+ return;
+
std::polymorphic<std::vector<int, UneqAlloc>, ScopedAlloc>
i14(std::allocator_arg, ScopedAlloc(11, 22),
std::in_place_type<std::vector<int, UneqAlloc>>);
test_forwarding_ctor();
test_inplace_ctor();
return true;
- });
+ }());
}
VERIFY( *i4 == src );
VERIFY( i4->get_personality() == -2 );
+ if (std::is_constant_evaluated())
+ return;
+
const VecDerived<int, UneqAlloc> v{1, 2, 3, 4, 5};
// Object is constructed using allocator-aware constructor.
std::polymorphic<Base, ScopedAlloc>
VERIFY( *i7 == il );
VERIFY( i7->get_personality() == 42 );
+ if (std::is_constant_evaluated())
+ return;
+
std::polymorphic<Base, ScopedAlloc>
i8(std::allocator_arg, ScopedAlloc(11, 22),
std::in_place_type<VecDerived<int, UneqAlloc>>);
test_forwarding_ctor();
test_inplace_ctor();
return true;
- });
+ }());
}
using Polymorphic = std::polymorphic<Base, tracker_allocator<Base>>;
const Polymorphic val(std::in_place_type<Derived>, 1, 2, 3);
-constexpr void
+void
verifyNoAllocations()
{
VERIFY( Counter::get_allocation_count() == 0 );
VERIFY( Counter::get_destruct_count() == 0 );
}
-constexpr void
+void
test_ctor()
{
std::optional<Polymorphic> src;
verifyNoAllocations();
}
-constexpr void
+void
test_assign()
{
std::optional<Polymorphic> src;
verifyNoAllocations();
}
-constexpr void
+void
test_swap()
{
const Polymorphic val1(std::in_place_type<Derived>, 1, 2, 3);
verifyNoAllocations();
}
-constexpr void
+void
test_valueless()
{
auto e = [] {
}
constexpr void
-test_all()
+test_constexpr()
{
- test_ctor();
- test_assign();
- test_swap();
- test_valueless();
+ using Polymorphic = std::polymorphic<Base, __gnu_test::uneq_allocator<Base>>;
+ const Polymorphic val(std::in_place_type<Derived>, 1, 2, 3);
+
+ std::optional<Polymorphic> src;
+ auto make = [&src, &val] -> Polymorphic&& {
+ src.emplace(val);
+ return std::move(*src);
+ };
+
+ Polymorphic i1(make());
+ VERIFY( src->valueless_after_move() );
+ VERIFY( *i1 == *val );
+
+ Polymorphic i2(std::allocator_arg, {}, make());
+ VERIFY( src->valueless_after_move() );
+ VERIFY( *i2 == *val );
+
+ i1 = make();
+ VERIFY( src->valueless_after_move() );
+ VERIFY( *i1 == *val );
+
+ auto(std::move(i1));
+ i1 = make();
+ VERIFY( *i1 == *val );
+ VERIFY( src->valueless_after_move() );
+
+ const Polymorphic val1(std::in_place_type<Derived>, 1, 2, 3);
+ const Polymorphic val2(std::in_place_type<Derived>, 2, 4, 6);
+
+ Polymorphic s1(val1);
+ Polymorphic s2(val2);
+ s1.swap(s2);
+ VERIFY( *s2 == *val1 );
+ VERIFY( *s1 == *val2 );
+
+ auto(std::move(s1));
+ s1.swap(s2);
+ VERIFY( *s1 == *val1 );
+ VERIFY( s2.valueless_after_move() );
+
+ auto e = [] {
+ Polymorphic res(std::in_place_type<Derived>);
+ auto(std::move(res));
+ return res;
+ };
+
+ Polymorphic e1(e());
+ VERIFY( e1.valueless_after_move() );
+
+ Polymorphic e2(std::allocator_arg, {}, e());
+ VERIFY( e2.valueless_after_move() );
+
+ Polymorphic e3(val);
+ e3 = e();
+ e3 = e();
}
int main()
{
- test_all();
+ test_ctor();
+ test_assign();
+ test_swap();
+ test_valueless();
+ test_constexpr();
static_assert([] {
- test_all();
+ test_constexpr();
return true;
- });
+ }());
}
using __gnu_test::tracker_allocator;
using Counter = __gnu_test::tracker_allocator_counter;
-constexpr void
+void
verifyNoAllocations()
{
VERIFY( Counter::get_allocation_count() == 0 );
}
template<bool Propagate>
-constexpr void
+void
test_ctor()
{
using PropAlloc = propagating_allocator<int, Propagate>;
}
template<bool Propagate>
-constexpr void
+void
test_assign()
{
using PropAlloc = propagating_allocator<int, Propagate>;
}
template<bool Propagate>
-constexpr void
+void
test_swap()
{
using PropAlloc = propagating_allocator<int, Propagate>;
}
template<bool Propagate>
-constexpr void
+void
test_valueless()
{
using PropAlloc = propagating_allocator<int, Propagate>;
}
template<bool Propagate>
-constexpr void
+void
test_all()
{
test_ctor<Propagate>();
{
test_all<true>();
test_all<false>();
-
- static_assert([] {
- test_all<true>();
- test_all<false>();
- return true;
- });
}
}
// Implement swap for underlying allocators that might need it.
- friend inline void
+ friend void
swap(tracker_allocator& a, tracker_allocator& b)
{
using std::swap;
{
typedef __gnu_cxx::__alloc_traits<Alloc> AllocTraits;
- Alloc& base() { return *this; }
- const Alloc& base() const { return *this; }
- void swap_base(Alloc& b) { using std::swap; swap(b, this->base()); }
-
public:
typedef typename check_consistent_alloc_value_type<Tp, Alloc>::value_type
value_type;
typename AllocTraits::template rebind<Tp1>::other> other;
};
+ _GLIBCXX_CONSTEXPR
uneq_allocator() _GLIBCXX_USE_NOEXCEPT
: personality(0) { }
+ _GLIBCXX_CONSTEXPR
uneq_allocator(int person) _GLIBCXX_USE_NOEXCEPT
: personality(person) { }
#endif
template<typename Tp1>
+ _GLIBCXX_CONSTEXPR
uneq_allocator(const uneq_allocator<Tp1,
typename AllocTraits::template rebind<Tp1>::other>& b)
_GLIBCXX_USE_NOEXCEPT
: personality(b.get_personality()) { }
- ~uneq_allocator() _GLIBCXX_USE_NOEXCEPT
- { }
-
- int get_personality() const { return personality; }
+ _GLIBCXX_CONSTEXPR int get_personality() const { return personality; }
+ _GLIBCXX20_CONSTEXPR
pointer
allocate(size_type n, const void* = 0)
{
pointer p = AllocTraits::allocate(*this, n);
+ if (std::__is_constant_evaluated())
+ return p;
+
try
{
get_map().insert(map_type::value_type(reinterpret_cast<void*>(p),
return p;
}
+ _GLIBCXX14_CONSTEXPR
void
deallocate(pointer p, size_type n)
{
VERIFY( p );
- map_type::iterator it = get_map().find(reinterpret_cast<void*>(p));
- VERIFY( it != get_map().end() );
+ if (!std::__is_constant_evaluated())
+ {
+ map_type::iterator it = get_map().find(reinterpret_cast<void*>(p));
+ VERIFY( it != get_map().end() );
+
+ // Enforce requirements in Table 32 about deallocation vs
+ // allocator equality.
+ VERIFY( it->second == personality );
- // Enforce requirements in Table 32 about deallocation vs
- // allocator equality.
- VERIFY( it->second == personality );
+ get_map().erase(it);
+ }
- get_map().erase(it);
AllocTraits::deallocate(*this, p, n);
}
private:
// ... yet swappable!
- friend inline void
+ friend _GLIBCXX_CONSTEXPR void
swap(uneq_allocator& a, uneq_allocator& b)
{
std::swap(a.personality, b.personality);
- a.swap_base(b);
+ using std::swap;
+ swap(static_cast<Alloc&>(a), static_cast<Alloc&>(b));
}
template<typename Tp1>
- friend inline bool
+ friend _GLIBCXX_CONSTEXPR bool
operator==(const uneq_allocator& a,
const uneq_allocator<Tp1,
typename AllocTraits::template rebind<Tp1>::other>& b)
{ return a.personality == b.get_personality(); }
template<typename Tp1>
- friend inline bool
+ friend _GLIBCXX_CONSTEXPR bool
operator!=(const uneq_allocator& a,
const uneq_allocator<Tp1,
typename AllocTraits::template rebind<Tp1>::other>& b)
typedef __gnu_cxx::__alloc_traits<Alloc> AllocTraits;
typedef uneq_allocator<Tp, Alloc> base_alloc;
- base_alloc& base() { return *this; }
- const base_alloc& base() const { return *this; }
- void swap_base(base_alloc& b) { swap(b, this->base()); }
+ _GLIBCXX14_CONSTEXPR void
+ swap_base(base_alloc& b)
+ {
+ using std::swap;
+ swap(b, static_cast<base_alloc&>(*this));
+ }
typedef std::integral_constant<bool, Propagate> trait_type;
typename AllocTraits::template rebind<Up>::other> other;
};
+ constexpr
propagating_allocator(int i) noexcept
: base_alloc(i)
{ }
template<typename Up>
+ constexpr
propagating_allocator(const propagating_allocator<Up, Propagate,
typename AllocTraits::template rebind<Up>::other>& a)
noexcept
propagating_allocator(const propagating_allocator&) noexcept = default;
+ _GLIBCXX14_CONSTEXPR
propagating_allocator&
operator=(const propagating_allocator& a) noexcept
{
}
template<bool P2>
+ _GLIBCXX14_CONSTEXPR
propagating_allocator&
operator=(const propagating_allocator<Tp, P2, Alloc>& a) noexcept
{
}
// postcondition: LWG2593 a.get_personality() un-changed.
+ constexpr
propagating_allocator(propagating_allocator&& a) noexcept
- : base_alloc(std::move(a.base()))
+ : base_alloc(static_cast<base_alloc&&>(a))
{ }
// postcondition: LWG2593 a.get_personality() un-changed
+ _GLIBCXX14_CONSTEXPR
propagating_allocator&
operator=(propagating_allocator&& a) noexcept
{
typedef trait_type propagate_on_container_move_assignment;
typedef trait_type propagate_on_container_swap;
- propagating_allocator select_on_container_copy_construction() const
+ constexpr propagating_allocator
+ select_on_container_copy_construction() const
{ return Propagate ? *this : propagating_allocator(); }
};
: state(a.state)
{ }
- constexpr T*
+ _GLIBCXX14_CONSTEXPR T*
allocate(std::size_t n)
{ return std::allocator<T>().allocate(n); }
- constexpr void
+ _GLIBCXX14_CONSTEXPR void
deallocate(T* p, std::size_t n)
{ std::allocator<T>().deallocate(p, n); }
ExplicitConsAlloc() { }
template<typename Up>
- explicit
+ explicit _GLIBCXX_CONSTEXPR
ExplicitConsAlloc(const ExplicitConsAlloc<Up>&) { }
template<typename Up>
CustomPointerAlloc() = default;
template<typename Up>
+ constexpr
CustomPointerAlloc(const CustomPointerAlloc<Up>&) { }
template<typename Up>
typedef Ptr<void> void_pointer;
typedef Ptr<const void> const_void_pointer;
+ _GLIBCXX14_CONSTEXPR
pointer allocate(std::size_t n, const_void_pointer = {})
{ return pointer(std::allocator<Tp>::allocate(n)); }
+ _GLIBCXX14_CONSTEXPR
void deallocate(pointer p, std::size_t n)
{ std::allocator<Tp>::deallocate(std::addressof(*p), n); }
};
explicit operator bool() const noexcept { return value != nullptr; }
- friend inline bool
+ friend constexpr bool
operator==(NullablePointer lhs, NullablePointer rhs) noexcept
{ return lhs.value == rhs.value; }
- friend inline bool
+ friend constexpr bool
operator!=(NullablePointer lhs, NullablePointer rhs) noexcept
{ return lhs.value != rhs.value; }
protected:
- explicit NullablePointer(Ptr p) noexcept : value(p) { }
+ constexpr explicit NullablePointer(Ptr p) noexcept : value(p) { }
Ptr value;
};
struct NullablePointer<void>
{
NullablePointer() = default;
- NullablePointer(std::nullptr_t) noexcept { }
- explicit NullablePointer(const volatile void*) noexcept { }
+ constexpr NullablePointer(std::nullptr_t) noexcept { }
+ constexpr explicit NullablePointer(const volatile void*) noexcept { }
- explicit operator bool() const noexcept { return false; }
+ constexpr explicit operator bool() const noexcept { return false; }
- friend inline bool
+ friend constexpr bool
operator==(NullablePointer, NullablePointer) noexcept
{ return true; }
- friend inline bool
+ friend constexpr bool
operator!=(NullablePointer, NullablePointer) noexcept
{ return false; }
};