[/
Copyright 2017-2021 Glen Joseph Fernandes
(glenjofe@gmail.com)

Distributed under the Boost Software License, Version 1.0.
(http://www.boost.org/LICENSE_1_0.txt)
]

[section:pointer_traits pointer_traits]

[simplesect Authors]

* Glen Fernandes

[endsimplesect]

[section Overview]

The header <boost/core/pointer_traits.hpp> provides the class template
`boost::pointer_traits` to facilitate use of pointer-like types. The C++11
standard library introduced `std::pointer_traits` along with an allocator
model which supported pointer-like types in addition to plain raw pointers.
This implementation also supports C++98.

It also provides the function template `boost::to_address` to obtain a raw
pointer from an object of any pointer-like type.

[endsect]

[section Examples]

The following example allocates storage and constructs an object in that
storage using an allocator.

```
template<class Allocator>
void function(Allocator& a)
{
    auto p = a.allocate(1);
    std::allocator_traits<Allocator>::construct(a, boost::to_address(p));
}
```

[endsect]

[section Reference]

```
namespace boost {

template<class T>
struct pointer_traits {
    typedef T pointer;
    typedef ``['see below]`` element_type;
    typedef ``['see below]`` difference_type;

    template<class U>
    struct rebind_to {
        typedef ``['see below]`` type;
    };

    template<class U>
    using rebind = typename rebind_to<U>::type;

    static pointer pointer_to(element_type& v);
};

template<class T>
struct pointer_traits<T*> {
    typedef T* pointer;
    typedef T element_type;
    typedef std::ptrdiff_t difference_type;

    template<class U>
    struct rebind_to {
        typedef U* type;
    };

    template<class U>
    using rebind = typename rebind_to<U>::type;

    static pointer pointer_to(``['see below]`` v) noexcept;
};

template<class T>
constexpr T* to_address(T* v) noexcept;

template<class T>
auto to_address(const T& v) noexcept;

} // boost
```

[section Overview]

If the member type `element_type` is not defined, then all other members are
also not defined (`pointer_traits` is SFINAE-friendly).

[endsect]

[section Member types]

[variablelist
[[`typedef` ['see below] `element_type;`]
[`T::element_type` if such a type exists; otherwise `U` if `T` is a class
  template instantiation of the form `Pointer<U, Args>`, where `Args` is zero
  or more type arguments; otherwise the member is not defined.]]
[[`typedef` ['see below] `difference_type;`]
[`T::difference_type` if such a type exists; otherwise `std::ptrdiff_t`.]]
[[`template<class U> struct rebind_to { typedef` ['see below] `type; };`]
[`type` is `T::rebind<U>` if such a type exists; otherwise, `Pointer<V, Args>`
  if `T` is a class template instantiation of the form `Pointer<T, Args>`,
  where `Args` is zero or more type arguments; otherwise, the member is not
  defined.]]]

[endsect]

[section Member functions]

[variablelist
[[`static pointer pointer_traits::pointer_to(element_type& v);`]
[[variablelist
[[Remark]
[If `element_type` is a void type, or if `T::pointer_to(v)` is not well formed,
  this member is not defined.]]
[[Returns]
[A pointer to `v` obtained by calling `T::pointer_to(v)`.]]]]]
[[`static pointer pointer_traits<T*>::pointer_to(element_type& v) noexcept;`]
[[variablelist
[[Remark]
[If `element_type` is a void type, this member is not defined.]]
[[Returns][`addressof(v)`.]]]]]]

[endsect]

[section Optional members]

[variablelist
[[`static element_type* to_address(pointer v) noexcept;`]
[[variablelist
[[Returns]
[A pointer of type `element_type*` that references the same location as the
  argument `p`.]]
[[Note]
[This function should be the inverse of `pointer_to`. If defined, it
  customizes the behavior of the non-member function `to_address`.]]]]]]

[endsect]

[section Free functions]

[variablelist
[[`template<class T> constexpr T* to_address(T* v) noexcept;`]
[[variablelist
[[Returns][`v`.]]]]]
[[`template<class T> auto to_address(const T& v) noexcept;`]
[[variablelist
[[Returns][`pointer_traits<T>::to_address(v)` if that
  expression is well-formed, otherwise `to_address(v.operator->())`.]]]]]]

[endsect]

[endsect]

[section Acknowledgments]

Glen Fernandes implemented `pointer_traits` and `to_address` with reviews and
guidance from Peter Dimov.

[endsect]

[endsect]
