Namespaces
Variants

std:: to_address

From cppreference.net
Memory management library
( exposition only* )
Allocators
Uninitialized memory algorithms
Constrained uninitialized memory algorithms
Memory resources
Uninitialized storage (until C++20)
( until C++20* )
( until C++20* )
( until C++20* )

Garbage collector support (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)
(C++11) (until C++23)
Определено в заголовке <memory>
template < class Ptr >
constexpr auto to_address ( const Ptr & p ) noexcept ;
(1) (начиная с C++20)
template < class T >
constexpr T * to_address ( T * p ) noexcept ;
(2) (начиная с C++20)

Получите адрес, представленный p без создания ссылки на объект, указываемый p .

1) Перегрузка умного указателя : Если выражение std:: pointer_traits < Ptr > :: to_address ( p ) корректно формируется, возвращает результат этого выражения. В противном случае возвращает std :: to_address ( p. operator - > ( ) ) .
2) Перегрузка с сырым указателем: Если T является типом функции, программа некорректна. В противном случае возвращает p без изменений.

Содержание

Параметры

p - умный или сырой указатель

Возвращаемое значение

Необработанный указатель, представляющий тот же адрес, что и p .

Возможная реализация

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->());
}

Примечания

std::to_address может использоваться даже когда p не ссылается на хранилище, в котором сконструирован объект, в таком случае std:: addressof ( * p ) не может быть использован, поскольку нет валидного объекта для привязки параметра std:: addressof .

Перегруженная версия std::to_address для умных указателей анализирует специализацию std:: pointer_traits < Ptr > . Если создание экземпляра этой специализации само по себе некорректно (обычно из-за невозможности определить element_type ), это приводит к жёсткой ошибке за пределами непосредственного контекста и делает программу некорректной.

std::to_address также может использоваться с итераторами, удовлетворяющими требованиям std::contiguous_iterator .

Макрос тестирования возможностей Значение Стандарт Возможность
__cpp_lib_to_address 201711L (C++20) Утилита для преобразования указателя в сырой указатель ( std::to_address )

Пример

#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);
}

Смотрите также

предоставляет информацию о указательноподобных типах
(шаблон класса)
[static] (C++20) (optional)
получает сырой указатель из умного указателя (обратная операция к pointer_to )
(публичная статическая функция-член std::pointer_traits<Ptr> )