2019-05-14 Jonathan Wakely <jwakely@redhat.com>
+ * testsuite/20_util/allocator_traits/members/allocate_hint_nonpod.cc:
+ Use operator-> to access raw pointer member.
+ * testsuite/23_containers/vector/59829.cc: Likewise.
+ * testsuite/23_containers/vector/bool/80893.cc: Likewise.
+ * testsuite/libstdc++-prettyprinters/cxx11.cc: Use NullablePointer.
+ * testsuite/util/testsuite_allocator.h (NullablePointer): New utility
+ for tests.
+ (PointerBase, PointerBase_void): Derive from NullablePointer and use
+ its constructors and equality operators. Change converting
+ constructors to use operator-> to access private member of the other
+ pointer type.
+ (PointerBase_void::operator->()): Add, for access to private member.
+ (operator-(PointerBase, PointerBase)): Change to hidden friend.
+ (operator==(PointerBase, PointerBase)): Remove.
+ (operator!=(PointerBase, PointerBase)): Remove.
+
* python/libstdcxx/v6/printers.py (UniquePointerPrinter.__init__): Do
not assume field called _M_head_impl is the first tuple element.
* testsuite/libstdc++-prettyprinters/compat.cc: Make tuple
#include <string>
#include <memory>
#include <iostream>
+#include "../util/testsuite_allocator.h" // NullablePointer
typedef std::tuple<int, int> ExTuple;
std::unique_ptr<datum> global;
-struct Deleter
-{
- // Deleter is not an empty class:
- int deleter_member = -1;
- // But pointer is an empty class:
- struct pointer
- {
- pointer(const void* = nullptr) { }
- explicit operator bool() const noexcept { return false; }
- friend bool operator==(pointer, pointer) noexcept { return true; }
- friend bool operator!=(pointer, pointer) noexcept { return false; }
- };
- void operator()(pointer) const noexcept { }
-};
-
int
main()
{
std::unique_ptr<data>& rarrptr = arrptr;
// { dg-final { regexp-test rarrptr {std::unique_ptr.datum \[\]. = {get\(\) = 0x.*}} } }
+ struct Deleter
+ {
+ int deleter_member = -1;
+ using pointer = __gnu_test::NullablePointer<void>;
+ void operator()(pointer) const noexcept { }
+ };
+ static_assert( !std::is_empty<Deleter>(), "Deleter is not empty" );
+ static_assert( std::is_empty<Deleter::pointer>(), "but pointer is empty" );
+
std::unique_ptr<int, Deleter> empty_ptr;
// { dg-final { note-test empty_ptr {std::unique_ptr<int> = {get() = {<No data fields>}}} } }
std::unique_ptr<int, Deleter>& rempty_ptr = empty_ptr;
{ std::allocator<Tp>::deallocate(std::addressof(*p), n); }
};
+ // A class type meeting *only* the Cpp17NullablePointer requirements.
+ // Can be used as a base class for fancy pointers (like PointerBase, below)
+ // or to wrap a built-in pointer type to remove operations not required
+ // by the Cpp17NullablePointer requirements (dereference, increment etc.)
+ template<typename Ptr>
+ struct NullablePointer
+ {
+ // N.B. default constructor does not initialize value
+ NullablePointer() = default;
+ NullablePointer(std::nullptr_t) noexcept : value() { }
+
+ explicit operator bool() const noexcept { return value == nullptr; }
+
+ friend inline bool
+ operator==(NullablePointer lhs, NullablePointer rhs) noexcept
+ { return lhs.value == rhs.value; }
+
+ friend inline bool
+ operator!=(NullablePointer lhs, NullablePointer rhs) noexcept
+ { return lhs.value != rhs.value; }
+
+ protected:
+ explicit NullablePointer(Ptr p) noexcept : value(p) { }
+ Ptr value;
+ };
+
+ // NullablePointer<void> is an empty type that models Cpp17NullablePointer.
+ template<>
+ struct NullablePointer<void>
+ {
+ NullablePointer() = default;
+ NullablePointer(std::nullptr_t) noexcept { }
+ explicit NullablePointer(const volatile void*) noexcept { }
+
+ explicit operator bool() const noexcept { return false; }
+
+ friend inline bool
+ operator==(NullablePointer, NullablePointer) noexcept
+ { return true; }
+
+ friend inline bool
+ operator!=(NullablePointer, NullablePointer) noexcept
+ { return false; }
+ };
+
// Utility for use as CRTP base class of custom pointer types
template<typename Derived, typename T>
- struct PointerBase
+ struct PointerBase : NullablePointer<T*>
{
typedef T element_type;
typedef Derived pointer;
typedef T& reference;
- T* value;
+ using NullablePointer<T*>::NullablePointer;
- explicit PointerBase(T* p = nullptr) : value(p) { }
-
- PointerBase(std::nullptr_t) : value(nullptr) { }
+ // Public (but explicit) constructor from raw pointer:
+ explicit PointerBase(T* p) noexcept : NullablePointer<T*>(p) { }
template<typename D, typename U,
typename = decltype(static_cast<T*>(std::declval<U*>()))>
- PointerBase(const PointerBase<D, U>& p) : value(p.value) { }
+ PointerBase(const PointerBase<D, U>& p)
+ : NullablePointer<T*>(p.operator->()) { }
+
+ T& operator*() const { return *this->value; }
+ T* operator->() const { return this->value; }
+ T& operator[](difference_type n) const { return this->value[n]; }
- T& operator*() const { return *value; }
- T* operator->() const { return value; }
- T& operator[](difference_type n) const { return value[n]; }
+ Derived& operator++() { ++this->value; return derived(); }
+ Derived& operator--() { --this->value; return derived(); }
- Derived& operator++() { ++value; return derived(); }
- Derived operator++(int) { Derived tmp(derived()); ++value; return tmp; }
- Derived& operator--() { --value; return derived(); }
- Derived operator--(int) { Derived tmp(derived()); --value; return tmp; }
+ Derived operator++(int) { return Derived(this->value++); }
- Derived& operator+=(difference_type n) { value += n; return derived(); }
- Derived& operator-=(difference_type n) { value -= n; return derived(); }
+ Derived operator--(int) { return Derived(this->value--); }
- explicit operator bool() const { return value != nullptr; }
+ Derived& operator+=(difference_type n)
+ {
+ this->value += n;
+ return derived();
+ }
+
+ Derived& operator-=(difference_type n)
+ {
+ this->value -= n;
+ return derived();
+ }
Derived
operator+(difference_type n) const
}
private:
+ friend std::ptrdiff_t operator-(PointerBase l, PointerBase r)
+ { return l.value - r.value; }
+
Derived&
derived() { return static_cast<Derived&>(*this); }
derived() const { return static_cast<const Derived&>(*this); }
};
- template<typename D, typename T>
- std::ptrdiff_t operator-(PointerBase<D, T> l, PointerBase<D, T> r)
- { return l.value - r.value; }
-
- template<typename D, typename T>
- bool operator==(PointerBase<D, T> l, PointerBase<D, T> r)
- { return l.value == r.value; }
-
- template<typename D, typename T>
- bool operator!=(PointerBase<D, T> l, PointerBase<D, T> r)
- { return l.value != r.value; }
-
- // implementation for void specializations
- template<typename T>
- struct PointerBase_void
+ // implementation for pointer-to-void specializations
+ template<typename T>
+ struct PointerBase_void : NullablePointer<T*>
{
typedef T element_type;
typedef std::ptrdiff_t difference_type;
typedef std::random_access_iterator_tag iterator_category;
- T* value;
+ using NullablePointer<T*>::NullablePointer;
- explicit PointerBase_void(T* p = nullptr) : value(p) { }
+ T* operator->() const { return this->value; }
template<typename D, typename U,
typename = decltype(static_cast<T*>(std::declval<U*>()))>
- PointerBase_void(const PointerBase<D, U>& p) : value(p.value) { }
-
- explicit operator bool() const { return value != nullptr; }
+ PointerBase_void(const PointerBase<D, U>& p)
+ : NullablePointer<T*>(p.operator->()) { }
};
- template<typename Derived>
+ template<typename Derived>
struct PointerBase<Derived, void> : PointerBase_void<void>
{
using PointerBase_void::PointerBase_void;
typedef Derived pointer;
};
- template<typename Derived>
+ template<typename Derived>
struct PointerBase<Derived, const void> : PointerBase_void<const void>
{
using PointerBase_void::PointerBase_void;