Skip to content

Latest commit

 

History

History
131 lines (102 loc) · 4.54 KB

make_from_tuple.md

File metadata and controls

131 lines (102 loc) · 4.54 KB

make_from_tuple

  • tuple[meta header]
  • function template[meta id-type]
  • std[meta namespace]
  • cpp17[meta cpp]
namespace std {
  template <class T, class Tuple>
  constexpr T make_from_tuple(Tuple&& t);
}

概要

tuple-likeな型Tupleのオブジェクトに含まれる値から型Tのオブジェクトを構築する。

要件

Tのコンストラクタの内のいずれか一つが、型Tupleに含まれる全ての型の値をその順番通りに受け入れ可能であること。それができない場合はコンパイルエラーとなる。
また、型Tの初期化はそのコンストラクタで行われ集成体初期化は考慮されない。つまり、Tupleに含まれる型が空かただ一つのTでない場合、型Tは集成体(aggregate)であってはならない(C++17のみ、C++20以降はok)。

引数

  • t -- tuple-likeな型Tupleのオブジェクト

tuple-likeな型とは主にstd::tupleの事であるが、std::pairstd::arrayのようにstd::tupleと同じような扱いができる型も含んでいる。
より詳細には、std::get(インデックス指定)とstd::tuple_sizeが適用可能な型である。

戻り値

Tupleに含まれる型の値をその順番通りに型Tのコンストラクタにstd::forwardして構築されたTのオブジェクト。

例外

Tupleに含まれる型の値を受け取るTのコンストラクタが例外を送出する可能性がある場合は、この関数も例外を送出しうる。

備考

構築したい型Tは引数からの推論ができないので、明示的に指定する必要がある。

また、値のコピー省略保証に対応するコンパイラであれば型Tはムーブ可能である必要はない(戻り値のTのオブジェクトは呼び出し元で構築される)。

実装例

template<class T, class Tuple, std::size_t... Index>
constexpr T make_from_tuple_impl(Tuple&& t, std::index_sequence<Index...>){
  return T(std::get<Index>(std::forward<Tuple>(t))...);
}

template <class T, class Tuple>
constexpr T make_from_tuple(Tuple&& t) {
  return make_from_tuple_impl<T>(std::forward<Tuple>(t), std::make_index_sequence<std::tuple_size_v<std::remove_reference_t<Tuple>>>{});
}
  • std::forward[link /reference/utility/forward.md]
  • std::make_index_sequence[link /reference/utility/make_index_sequence.md]
  • std::index_sequence[link /reference/utility/index_sequence.md]
  • std::decay_t[link /reference/type_traits/decay.md]

#include <tuple>
#include <array>
#include <iostream>

struct sample {
  sample(int a, int b, double c, const char* d) {
    std::cout << a << ", " << b << ", " << c << ", " << d << std::endl;
  }

  sample(int a, double b) {
    std::cout << a << ", " << b << std::endl;
  }

  sample(int a1, int a2, int a3, int a4) {
    std::cout << a1 << ", " << a2 << ", " << a3 << ", " << a4 << std::endl;
  }

  //あらゆるムーブ・コピー操作をdelete
  sample(sample&&) = delete;
  sample(const sample&) = delete;
  sample& operator=(sample&&) = delete;
  sample& operator=(const sample&) = delete;
};

int main()
{
  {
    auto t = std::make_tuple(0, 10, 20.0, "Hello world.");

    //std::tuple<int, int, double, const char*>からの構築
    auto s = std::make_from_tuple<sample>(std::move(t));
  }

  {
    auto p = std::make_pair(30, 40.0);

    //std::pair<int, double>からの構築
    auto s = std::make_from_tuple<sample>(std::move(p));
  }

  {
    std::array<int, 4> a = {1, 2, 3, 4};

    //std::arrayからの構築
    auto s = std::make_from_tuple<sample>(std::move(a));
  }
}
  • std::make_from_tuple[color ff0000]
  • std::make_tuple[link ../tuple/make_tuple.md]

出力

0, 10, 20, Hello world.
30, 40
1, 2, 3, 4

バージョン

言語

  • C++17

処理系

関連項目

参照