最終更新日時(UTC):
が更新

履歴 編集

concept
<concepts>

std::convertible_to(C++20)

namespace std {
  template<class From, class To>
  concept convertible_to =
    is_convertible_v<From, To> &&
    requires(add_rvalue_reference_t<From> (&f)()) {
      static_cast<To>(f());
    };
}

概要

convertible_toは、Fromに指定された型および値カテゴリから型Toへ変換可能であることを表すコンセプトである。

このコンセプトを満たすためにはFromからToへ暗黙的にも明示的にも変換可能であり、それら暗黙的および明示的な変換は同じ結果とならなければならない。

モデル

FromR = add_rvalue_reference_t<From>として、説明のための関数test(), f()を以下のように定義、宣言する。

To test(FromR (&func)()) {
  return func();
}

FromR f();

このtest()関数、型FromR, To及び、等しさを保持FromR型を返す引数なしの関数fについて、以下の条件を満たす場合に限って型From, Toconvertible_toのモデルである。

  • 次のどちらかを満たす
    • Toオブジェクト型でもオブジェクトへの参照型でもない
    • static_cast<To>(f())test(f)は等しい
  • 次のいずれかを満たす
    • FromRはオブジェクトへの参照型ではない
    • FromRが非const右辺値参照型の場合、f()の呼び出しによって参照されるオブジェクトの状態は、上記の式の実行の後でも有効だが未規定となる
      • 標準ライブラリの型のオブジェクトは特に指定がない場合、ムーブされた後の状態は有効だが未規定となる
    • f()の呼び出しによって参照されるオブジェクトは上記の式の実行によって変更されない

2つ目のor条件列に出てくる「上記の式」とは、static_cast<To>(f())test(f)のこと。

#include <iostream>
#include <concepts>

struct convert_int {
  operator int() { return 0; }
  convert_int(int){}
};

struct convert_double {
  explicit convert_double(double) {}
  explicit operator double() { return 0.0; }
};

// 明示的な変換と暗黙的な変換で結果が異なる例
struct vague_convert {
  operator int() { return -1; }
  explicit operator double() { return 1.0; }
};

int main()
{
  std::cout << std::boolalpha;

  std::cout << "--- fundamental type ---\n";
  std::cout << std::convertible_to<int, short> << std::endl;
  std::cout << std::convertible_to<short, int> << std::endl;
  std::cout << std::convertible_to<std::size_t, int> << std::endl;
  std::cout << std::convertible_to<int, std::size_t> << std::endl;
  std::cout << std::convertible_to<int, const int> << std::endl;
  std::cout << std::convertible_to<const int, int> << std::endl;
  std::cout << std::convertible_to<int, double> << std::endl;
  std::cout << std::convertible_to<double, int> << std::endl;
  std::cout << std::convertible_to<float, double> << std::endl;
  std::cout << std::convertible_to<double, float> << std::endl;
  std::cout << std::convertible_to<int*, const int*> << std::endl;
  std::cout << std::convertible_to<const int*, int*> << std::endl;

  std::cout << "\n--- program defined type ---\n";
  std::cout << std::convertible_to<convert_int, int> << std::endl;
  std::cout << std::convertible_to<int, convert_int> << std::endl;
  std::cout << std::convertible_to<convert_double, double> << std::endl;
  std::cout << std::convertible_to<double, convert_double> << std::endl;
  std::cout << std::convertible_to<vague_convert, int> << std::endl;
  std::cout << std::convertible_to<vague_convert, double> << std::endl;
}

出力

--- fundamental type ---
true
true
true
true
true
true
true
true
true
true
true
false

--- program defined type ---
true
true
false
false
true
true

バージョン

言語

  • C++20

処理系

関連項目

参照