namespace std {
template <class Ptr>
constexpr auto to_address(const Ptr& p) noexcept; // (1)
template <class T>
constexpr T* to_address(T* p) noexcept; // (2)
}
概要
ポインタと見なせるオブジェクトからアドレスを取得する。
要件
- (2) : 型
T
が関数ではないこと
戻り値
- (1) : 式
pointer_traits<Ptr>::to_address(p)
が有効であればその戻り値を返す。そうでなければ、to_address(p.operator->())
を返す - (2) :
p
を返す
例外
投げない
例
ポインタの例
#include <iostream>
#include <memory>
int main()
{
int x = 3;
int* p = &x;
// ポインタからアドレスを取得する。
// なにもせず、渡したものが返る
int* result1 = std::to_address(p);
std::cout << *result1 << std::endl;
// スマートポインタからアドレスを取得する。
// スマートポインタが所有権管理しているポインタが返る
std::shared_ptr<int> sp {new int(1)};
int* result2 = std::to_address(sp);
std::cout << *result2 << std::endl;
}
出力
3
1
イテレータの例
#include <iostream>
#include <vector>
int main()
{
std::vector<int> vec = {1, 2, 3, 4};
// vectorやstring等のイテレータはcontiguousではあるが、実装によってポインタではない場合がある
auto it = vec.begin();
auto end = vec.end();
// contiguousなイテレータをその要素へのポインタに変換する
int* p = std::to_address(it);
// 特に、終端イテレータからポインタへの変換で未定義動作を回避できる
int* ep = std::to_address(end);
// この様にしてしまうと、オブジェクトを指していないポインタのデリファレンスとなり未定義動作
//int* ep = &*end;
std::cout << *p << '\n';
std::cout << *(ep - 1);
}
出力
1
4
バージョン
言語
- C++20
処理系
- Clang: 6.0 ✅
- GCC: 8.1 ✅
- Visual C++: ??