Namespaces
Variants
Views
Actions

Difference between revisions of "cpp/memory/to address"

From cppreference.com
< cpp‎ | memory
m (the Ptr overload is first on this page, how about descriptive name)
(Link concept (and remove invisible character), to_address isn't disallowed on other iterators, it's just not guaranteed to be supported)
 
(6 intermediate revisions by 4 users not shown)
Line 2: Line 2:
 
{{cpp/memory/navbar}}
 
{{cpp/memory/navbar}}
 
{{dcl begin}}
 
{{dcl begin}}
{{dcl header | memory}}
+
{{dcl header|memory}}
{{dcl |num=1|since=c++20|1=
+
{{dcl|num=1|since=c++20|1=
 
template< class Ptr >
 
template< class Ptr >
constexpr auto to_address(const Ptr& p) noexcept;
+
constexpr auto to_address( const Ptr& p ) noexcept;
 
}}
 
}}
{{dcl | num=2 | since=c++20 |1=
+
{{dcl|num=2|since=c++20|1=
 
template< class T >
 
template< class T >
constexpr T* to_address(T* p) noexcept;
+
constexpr T* to_address( T* p ) noexcept;
 
}}
 
}}
 
{{dcl end}}
 
{{dcl end}}
  
Obtain the address represented by {{tt|p}} without forming a reference to the pointee.
+
Obtain the address represented by {{c|p}} without forming a reference to the object pointed to by {{c|p}}.
  
@1@ Fancy pointer overload: If the expression {{c|std::pointer_traits<Ptr>::to_address(p)}} is well-formed, returns the result of that expression. Otherwise, returns {{c|std::to_address(p.operator->())}}.
+
@1@ [[cpp/named_req/Allocator#Fancy pointers|Fancy pointer]] overload: If the expression {{c|std::pointer_traits<Ptr>::to_address(p)}} is well-formed, returns the result of that expression. Otherwise, returns {{c|std::to_address(p.operator->())}}.
 
@2@ Raw pointer overload: If {{tt|T}} is a function type, the program is ill-formed. Otherwise, returns {{c|p}} unmodified.
 
@2@ Raw pointer overload: If {{tt|T}} is a function type, the program is ill-formed. Otherwise, returns {{c|p}} unmodified.
  
 
===Parameters===
 
===Parameters===
 
{{par begin}}
 
{{par begin}}
{{par | p | fancy or raw pointer}}
+
{{par|p|fancy or raw pointer}}
 
{{par end}}
 
{{par end}}
  
 
===Return value===
 
===Return value===
Raw pointer that represents the same address as {{tt|p}} does.
+
Raw pointer that represents the same address as {{c|p}} does.
  
 
===Possible implementation===
 
===Possible implementation===
{{eq fun | 1=
+
{{eq fun|1=
 
template<class T>
 
template<class T>
 
constexpr T* to_address(T* p) noexcept
 
constexpr T* to_address(T* p) noexcept
Line 38: Line 38:
 
constexpr auto to_address(const T& p) noexcept
 
constexpr auto to_address(const T& p) noexcept
 
{
 
{
     if constexpr (requires{ std::pointer_traits<T>::to_address(p); }) {
+
     if constexpr (requires{ std::pointer_traits<T>::to_address(p); })
 
         return std::pointer_traits<T>::to_address(p);
 
         return std::pointer_traits<T>::to_address(p);
     } else {
+
     else
 
         return std::to_address(p.operator->());
 
         return std::to_address(p.operator->());
    }
 
 
}
 
}
 
}}
 
}}
  
 
===Notes===
 
===Notes===
{{tt|std::to_address}} can be used even when {{tt|p}} does not reference storage that has an object constructed in it, in which case {{c|std::addressof(*p)}} cannot be used because there's no valid object for the parameter of {{c|std::addressof}}<!--or the return value of fancy_pointer::operator* --> to bind to.
+
{{tt|std::to_address}} can be used even when {{c|p}} does not reference storage that has an object constructed in it, in which case {{c|std::addressof(*p)}} cannot be used because there is no valid object for the parameter of {{c|std::addressof}}<!--or the return value of fancy_pointer::operator* --> to bind to.
  
The fancy pointer overload of {{tt|to_address}} inspects the {{c|std::pointer_traits<Ptr>}} specialization. If instantiating that specialization is itself ill-formed (typically because {{tt|element_type}} cannot be defined), that results in a hard error outside the immediate context and renders the program ill-formed.
+
The fancy pointer overload of {{tt|std::to_address}} inspects the {{c|std::pointer_traits<Ptr>}} specialization. If instantiating that specialization is itself ill-formed (typically because {{tt|element_type}} cannot be defined), that results in a hard error outside the immediate context and renders the program ill-formed.
 +
 
 +
{{tt|std::to_address}} may additionally be used on iterators that satisfy {{lc|std::contiguous_iterator}}.
 +
 
 +
{{feature test macro|__cpp_lib_to_address|Utility to convert a pointer to a raw pointer ({{tt|std::to_address}})|value=201711L|std=C++20}}
  
 
===Example===
 
===Example===
Line 59: Line 62:
 
{
 
{
 
     auto p = a.allocate(1);
 
     auto p = a.allocate(1);
     try {
+
     try
 +
    {
 
         std::allocator_traits<A>::construct(a, std::to_address(p));
 
         std::allocator_traits<A>::construct(a, std::to_address(p));
     } catch (...) {
+
     }
 +
    catch (...)
 +
    {
 
         a.deallocate(p, 1);
 
         a.deallocate(p, 1);
 
         throw;
 
         throw;
Line 85: Line 91:
 
===See also===
 
===See also===
 
{{dsc begin}}
 
{{dsc begin}}
{{dsc inc | cpp/memory/dsc pointer_traits}}
+
{{dsc inc|cpp/memory/dsc pointer_traits}}
{{dsc inc | cpp/memory/pointer_traits/dsc to_address}}
+
{{dsc inc|cpp/memory/pointer_traits/dsc to_address}}
 
{{dsc end}}
 
{{dsc end}}
  
 
{{langlinks|ar|de|es|fr|it|ja|pl|pt|ru|zh}}
 
{{langlinks|ar|de|es|fr|it|ja|pl|pt|ru|zh}}

Latest revision as of 01:31, 12 July 2023

 
 
Utilities library
General utilities
Relational operators (deprecated in C++20)
 
Dynamic memory management
Uninitialized memory algorithms
Constrained uninitialized memory algorithms
Allocators
Garbage collection support
(C++11)(until C++23)
(C++11)(until C++23)
(C++11)(until C++23)
(C++11)(until C++23)
(C++11)(until C++23)
(C++11)(until C++23)



 
Defined in header <memory>
template< class Ptr >
constexpr auto to_address( const Ptr& p ) noexcept;
(1) (since C++20)
template< class T >
constexpr T* to_address( T* p ) noexcept;
(2) (since C++20)

Obtain the address represented by p without forming a reference to the object pointed to by p.

1) Fancy pointer overload: If the expression std::pointer_traits<Ptr>::to_address(p) is well-formed, returns the result of that expression. Otherwise, returns std::to_address(p.operator->()).
2) Raw pointer overload: If T is a function type, the program is ill-formed. Otherwise, returns p unmodified.

Contents

[edit] Parameters

p - fancy or raw pointer

[edit] Return value

Raw pointer that represents the same address as p does.

[edit] Possible implementation

template<class T>
constexpr T* to_address(T* p) noexcept
{
    static_assert(!std::is_function_v<T>);
    return p;
}
 
template<class T>
constexpr auto to_address(const T& p) noexcept
{
    if constexpr (requires{ std::pointer_traits<T>::to_address(p); })
        return std::pointer_traits<T>::to_address(p);
    else
        return std::to_address(p.operator->());
}

[edit] Notes

std::to_address can be used even when p does not reference storage that has an object constructed in it, in which case std::addressof(*p) cannot be used because there is no valid object for the parameter of std::addressof to bind to.

The fancy pointer overload of std::to_address inspects the std::pointer_traits<Ptr> specialization. If instantiating that specialization is itself ill-formed (typically because element_type cannot be defined), that results in a hard error outside the immediate context and renders the program ill-formed.

std::to_address may additionally be used on iterators that satisfy std::contiguous_iterator.

Feature-test macro Value Std Feature
__cpp_lib_to_address 201711L (C++20) Utility to convert a pointer to a raw pointer (std::to_address)

[edit] Example

#include <memory>
 
template<class A>
auto allocator_new(A& a)
{
    auto p = a.allocate(1);
    try
    {
        std::allocator_traits<A>::construct(a, std::to_address(p));
    }
    catch (...)
    {
        a.deallocate(p, 1);
        throw;
    }
    return p;
}
 
template<class A>
void allocator_delete(A& a, typename std::allocator_traits<A>::pointer p)
{
    std::allocator_traits<A>::destroy(a, std::to_address(p));
    a.deallocate(p, 1);
}
 
int main()
{
    std::allocator<int> a;
    auto p = allocator_new(a);
    allocator_delete(a, p);
}

[edit] See also

provides information about pointer-like types
(class template) [edit]
[static] (C++20)(optional)
obtains a raw pointer from a fancy pointer (inverse of pointer_to)
(public static member function of std::pointer_traits<Ptr>) [edit]