std::to_address
来自cppreference.com
在标头 <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> 的公开静态成员函数) |