以下の内容はhttps://yohhoy.hatenadiary.jp/entry/20250228/p1より取得しました。


Expansion statement for C++

プログラミング言語C++の次期標準C++2c(C++26)向けに提案されている展開文(Expansion statement)について。template for構文をもちいて本体処理を反復的にコンパイル時展開する。

2025-06-22追記:2025年6月会合にてP1306R5が採択され*1C++2c言語仕様に展開文(Expansion statement)が導入される。あわせて P2996R13 C++ Reflection(→id:yohhoy:20250305)も採択済み*2

// P1306R3: destructurable expression
auto tup = std::make_tuple(0, 'a', 3.14);
template for (auto elem : tup)
  std::println("{}", elem);
// 下記コードに展開される
auto&& tup = std::make_tuple(0, 'a', 3.14);
{ auto elem = std::get<0>(tup); std::println("{}", elem); }
{ auto elem = std::get<1>(tup); std::println("{}", elem); }
{ auto elem = std::get<2>(tup); std::println("{}", elem); }
// P1306R3: expansion-init-list
template for (auto elem : {0, 'a', 3.14})
  std::println("{}", elem);
// 下記コードに展開される
{ auto elem = 0;    std::println("{}", elem); }
{ auto elem = 'a';  std::println("{}", elem); }
{ auto elem = 3.14; std::println("{}", elem); }

C++2c向けに同時検討されているC++ Reflection機能と組み合わせると、全C++プログラマの夢(?)であった「列挙型の値から文字列への変換関数」をジェネリックに実装できる。

// P1306R3 + P2996(Reflection) + P3491(define_static_*)
#include <meta>  // P2996+P3491
#include <string_view>
#include <type_traits>

template <typename E>
  requires std::is_enum_v<E>
constexpr std::string_view enum_to_string(E value) {
  // リフレクション(reflection)演算子^^ + enumerators_ofメタ関数(P2996)
  //   列挙型Eの列挙子リストをstd::vector<std::meta::info>で返す
  // define_static_arrayメタ関数(P3491)
  //  コンパイル時vector<meta::info>から静的配列への参照(span)に変換
  template for (constexpr auto e :
    std::define_static_array(std::meta::enumerators_of(^^E)))
  {
    // リフレクション値(reflection value) eの型 == std::meta::info
    // スプライス式(splice-expression) [:e:] により列挙子の値を取得
    if (value == [:e:]) {
      // identifier_ofメタ関数
      //   列挙子eの識別子(名前)をstd::string_viewで返す
      return std::meta::identifier_of(e);
    }
  }
  return "<unnamed>";
}

2025-12-26追記:上記のenum_to_string関数実装にstd::define_static_arrayメタ関数(→id:yohhoy:20250629)利用を追記。StackOverflowの回答 What is `template for` in C++26? も参照のこと。

template for構文においても通常のfor構文と同じくbreak文/continue文をサポートする。コンパイル時展開はbreakcontinue制御によらず行われ、評価フェーズで実行パス分岐が行われることに注意。

// P1306R3
template for (auto v : {1,2,3,4,5,6,7,8,9}) {
  if (v % 2 == 0) continue;
  std::print("{} ", v);
  if (v % 5 == 0) break;
}
// 1 3 5

関連URL




以上の内容はhttps://yohhoy.hatenadiary.jp/entry/20250228/p1より取得しました。
このページはhttp://font.textar.tv/のウェブフォントを使用してます

不具合報告/要望等はこちらへお願いします。
モバイルやる夫Viewer Ver0.14