---
# System prepended metadata

title: 'std::in_place_type'
tags: [elkurin-daily-note, C++-General]

---

# std::in_place_type
テンプレート勉強会の続きとして、テンプレートのタグ付けとしてよく使われる[std::in_place_type](https://en.cppreference.com/w/cpp/utility/in_place)を確認する。

## std::in_place_typeとは
std::in_place_typeは以下のような定数。
```cpp=
template< class T >
inline constexpr std::in_place_type_t<T> in_place_type {};
```
inlineで定義される謎の空構造体である。  
これでは何もわからないので、std::in_place_type_tを理解する必要がある。

```cpp=
template< class T >
struct in_place_type_t { explicit in_place_type_t() = default; };
```
explicitなデフォルトコンストラクタだけを持つ構造体。受け取ったテンプレート引数である`T`も特に使われていない。これは何？  
これはいわゆるマーカーみたいなもので、型を実質変数のように扱える。  
例えば`in_place_type_<T>()`という型を引数に取る関数を宣言すると、そこに`in_place_type_t<vector>()`といった感じで型そのものの情報を受け渡すことができる。  
実際の使用例は次のセクションで見る。


他にも似たようなものでin_place, in_place_indexなどがあるが、これらも `*_t`が型テンプレートでConstructorのタグに使えるし、`_t`を取り除いたものが定数として宣言されており同様のタグの役割で使える。

## 使用例 in std::variant
[std::variant](https://en.cppreference.com/w/cpp/utility/variant)を見ながらstd::in_placeがどう嬉しいかを理解する。  

std::variantは格納されうる候補の型リストに含まれる型のオブジェクトを切り替えながら保持する記憶域型。

```cpp=
// A or B ro C の型の値を保持する変数になる
std::variant<A, B, C> v = A{};
```

そのstd::variantのconstructorでin_place_typeが引数になっているものがある。以下。
```cpp=
template< class T,
          class... Args >
constexpr explicit variant( std::in_place_type_t<T>,
                            Args&&... args );
```
このコンストラクタでは、第一引数にin_place_type_tのテンプレート型を持っており、これを指定することで型`T`を受け渡すことができる。  

今回はstd::variantの内部実装までは追わず、外から見てどうかけるかに着目する。
```cpp=
// 普通の使い方。どちらにマッチするか自明な際はこれで良い。
std::variant<std::string, int> var{"str"};

// 最初にin_place_typeをいれることで、なんの型を受け取っているのか明示できる
std::variant<std::string, vector_t, float> var3{
    std::in_place_type<std::string>, 4, 'A'
};
```

わかりやすくてめでたい。