最終更新日時(UTC): 2024年06月11日 13時45分38秒
Akira Takahashi が更新

履歴 編集

function template
<memory>

# std::to_address(C++20)

    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++: ??

## 参照

- P0653R2 Utility to convert a pointer to a raw pointer
- `pointer_traits` - Boost Core Library
- LWG Issue 3374. P0653 + P1006 should have made the other `std::to_address` overload `constexpr`