スポンサーリンク

C++でfunc(param=10);のように関数呼び出しに引数名を使用する方法を考える

やってできないことはない。実用性があるかどうかは別。これを使うと引数を与える順番を考えなくてよくなるのと、引数の意味が呼び出し側でわかるようになるので若干可読性が上がるかもしれない。

#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"
    );
}

実行結果

index: 5
count: 10
text: Hello, World!
title: My Title

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

日本語が含まれない投稿は無視されますのでご注意ください。(スパム対策)


この記事のトラックバックURL: