memory_to_address
memory_to_address (std::to_address)
<memory> 헤더에 정의되어 있어요. p가 가리키는 객체에 대한 참조를 만들지 않고 p가 나타내는 주소를 얻어요. fancy pointer와 원시 포인터 모두에 쓸 수 있어요. C++20부터 도입됐어요.
출처: cppreference
본문
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
p가 가리키는 객체에 대한 참조를 형성하지 않고 p가 나타내는 주소를 얻어요.
-
- Fancy pointer 오버로드:
std::pointer_traits<Ptr>::to_address(p)표현식이 well-formed이면 그 결과를, 아니면std::to_address(p.operator->())를 돌려줘요.
- Fancy pointer 오버로드:
-
- 원시 포인터 오버로드:
T가 함수 타입이면 ill-formed. 아니면p를 그대로 돌려줘요.
- 원시 포인터 오버로드:
매개변수
p: fancy 또는 원시 포인터
반환값
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->());
}
주의 (Notes)
std::to_address는 p가 객체가 구성된 저장 공간을 참조하지 않아도 쓸 수 있어요. 그 경우 std::addressof(*p)는 바인딩할 유효한 객체가 없어 쓸 수 없어요. fancy pointer 오버로드는 std::pointer_traits<Ptr> 특수화를 검사하며, 그 특수화 인스턴스화 자체가 ill-formed면 프로그램은 ill-formed예요. std::to_address는 std::contiguous_iterator를 만족하는 반복자에도 쓸 수 있어요.
기능 테스트 매크로는 __cpp_lib_to_address(201711L, C++20)예요.
예제
#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;
}
int main()
{
std::allocator<int> a;
auto p = allocator_new(a);
std::allocator_traits<A>::destroy(a, std::to_address(p));
a.deallocate(p, 1);
}