std::to_address
Определено в заголовке <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.
std::pointer_traits<Ptr>::to_address(p) корректно, возвращает результат этого выражения. В противном случае возвращает std::to_address(p.operator->()).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);
}
См. также
|
(C++11) | предоставляет информацию о типах, подобных указателям (шаблон класса) |
|
[статический] (C++20)(необязательно) | получает обычный указатель из расширенного указателя (обратная операция для pointer_to) (открытая статическая функция-член std::pointer_traits<Ptr>) |
© cppreference.com
Licensed under the Creative Commons Attribution-ShareAlike Unported License v3.0.
https://en.cppreference.com/cpp/memory/to_address