やってできないことはない。実用性があるかどうかは別。これを使うと引数を与える順番を考えなくてよくなるのと、引数の意味が呼び出し側でわかるようになるので若干可読性が上がるかもしれない。
#include <iostream> #include <type_traits>
// 型TがArgs...に含まれているかどうかを判定するメタ関数 template <typename T, typename... Args> constexpr bool is_contains_type = (std::is_same_v<T, Args> || ...);
// 可変引数テンプレートから特定の型Tで与えられた変数を取得する template<typename T, typename First, typename... Rest> decltype(auto) get_value(First&& first, Rest&&... rest) { if constexpr (std::is_same_v<T, std::decay_t<First> > == true) { return std::forward<First>(first); } // sizeof...(rest)で残りの引数の数をチェック else if constexpr (sizeof...(rest) > 0) { // 残りの引数restから T を探す return get_value<T>( std::forward<Rest>(rest)...); } else { static_assert(sizeof...(rest) > 0, "No matching type found in arguments."); } }
template<int ID> // IDを与えてusing時にそれぞれを違う型として認識されるようにする struct ArgString { std::string value; ArgString& operator=(const std::string& str) { value = str; return *this; } }; template<int ID> struct ArgInt { int value; ArgInt& operator=(int i) { value = i; return *this; } }; using Text = ArgString<0>; using Title = ArgString<1>; using Index = ArgInt<0>; using Count = ArgInt<1>; // グローバル引数として、関数に渡す時に指定する引数名を定義 Index index; Count count; Text text; Title title;
// print関数の定義 template <class... Args> void print(Args&&... args) {// argsにはindex,count,text,titleのいずれかが入っている Index index; Count count; Text text; Title title; if constexpr (is_contains_type<Index, std::decay_t<Args>...>) { auto&& arg = get_value<Index>( std::forward<Args>(args)... ); index = arg; // 引数の値をIndexに設定 } if constexpr (is_contains_type<Count, std::decay_t<Args>...>) { auto&& arg = get_value<Count>( std::forward<Args>(args)... ); count = arg; // 引数の値をCountに設定 } if constexpr (is_contains_type<Text, std::decay_t<Args>...>) { auto&& arg = get_value<Text>( std::forward<Args>(args)... ); text = arg; // 引数の値をTextに設定 } if constexpr (is_contains_type<Title, std::decay_t<Args>...>) { auto&& arg = get_value<Title>( std::forward<Args>(args)... ); title = arg; // 引数の値をTitleに設定 } // 各値を使用 std::cout << "index: " << index.value << std::endl; std::cout << "count: " << count.value << std::endl; std::cout << "text: " << text.value << std::endl; std::cout << "title: " << title.value << std::endl; }
int main() { print( index = 5, count = 10, text = "Hello, World!", title = "My Title" ); }
実行結果