std::to_address
来自cppreference.com
<tbody>
</tbody>
| 在标头 <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 所指向的地址,而不形成到被指向者的引用:
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->());
}
|
注解
即使在 p 引用的存储中无已构造的对象时,也能使用 std::to_address,该情况下不能用 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> 的公开静态成员函数)
|