以下の内容はhttps://pyopyopyo.hatenablog.com/entry/2025/04/28/000000より取得しました。


可変長テンプレートでパラメータ・パックを2つ同時に使う方法

c++の可変長テンプレートで2つの型リストKeysとValuesを使いたいとする
その場合は

  • リストの片方は std::tupleで一つの型にする
  • 残りのリストは 可変長テンプレートにする

とコーディングしやすい

template <typename KeyTuple, typename... Values_>
struct Foo { 
   using Keys = KeyTuple;
   using Values = std::tuple<Values_...>;
};

std:tuple で指定するリストは,長さが1以上のリスト,つまり要素を省略できないリストを選ぶと良い

これで

Foo<std::tuple<int, std::string>, bool> foo1;
Foo<std::tuple<int, std::string>> foo2;
Foo<std::tuple<int, std::string>, bool, int, float> foo3;

といったコードが書けるようになる

解説

可変長テンプレートを2つ指定することは可能で,以下のコードはコンパイルできる

template <typename... Keys_, typename... Values_>
struct Foo {};

Foo<int, double, std::string, char, bool> foo; 

しかしこれでは,どこまでがKeysで,どこからが Valuesが区別できない.

template <typename KeyTuple, typename... Values_>
struct Foo { 
   using Keys = KeyTyple;
   using Values = std::tuple<Values_...>;
};
Foo<std::tuple<int, double, std::string>, char, bool> foo; 

と書けば Values は charとboolの2つであることがわかる

内部的には Foo::KeysとFoo::Valuesはどちらも std::tuple なので,可変長テンプレートの恩恵は等しく受けられる


例えば型リストの長さを取る場合

template <typename KeyTuple, typename... Values_>
struct Foo { 
   using Keys = KeyTyple;
   using Values = std::tuple<Values_...>;
   static constexpr std::size_t KeyCount = std::tuple_size_v<Keys>;
   static constexpr std::size_t ValueCount = std::tuple_size_v<Values>;
};

keysをすべて std::cout に出力する場合

template <typename KeyTuple, typename... Values_>
struct Foo { 
   using Keys = KeyTyple;
   using Values = std::tuple<Values_...>;

  std::string keys_string() const {
     std::string oss; 
     std::apply([&oss](const auto&... e) {
            size_t n=0;
            ((oss << (n++?",":"") << e), ...);
        }, keys);
     return oss.str(); 
  }
};

Foo<std::tuple<int,std::string>, int> foo;

std::cout << foo.keys_string() << std::endl;

さらなる拡張

c++20の concepts を使うとより使いやすくなる

#include <tuple>
#include <type_traits>
#include <iostream>

template <typename T>
concept TupleType = requires {
    typename std::tuple_size<T>::type;
};

template <TupleType KeyTuple, typename... Values_>

これで

Foo<std::string, char, bool> foo; 

のような間違ったコードをコンパイル時エラーにできる




以上の内容はhttps://pyopyopyo.hatenablog.com/entry/2025/04/28/000000より取得しました。
このページはhttp://font.textar.tv/のウェブフォントを使用してます

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