スポンサーリンク

C++、可変引数テンプレート関数で、引数の型に応じた動作を定義する

可変引数テンプレートもそうだが、if constexprやtype_traits、型推論に右辺参照もあるのでかなり簡単に書けるようになっている。

#include <iostream>
#include <type_traits>

// 型TがArgs...に含まれているかどうかを判定するメタ関数
template <typename T, typename... Args>
constexpr bool is_contains_type = (std::is_same_v<T, Args> || ...);

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 <class... Args>
void print(Args&&... args) {

    if constexpr (is_contains_type<int, std::decay_t<Args>...>) {
        auto&& arg_int = get_value<int>( std::forward<Args>(args)... );
        std::cout << "int is " << arg_int << "\n";
    }

    if constexpr (is_contains_type<double, std::decay_t<Args>...>) {
        auto&& arg_double = get_value<double>(std::forward<Args>(args)... );
        std::cout << "double is "<< arg_double << "\n";
    }

    if constexpr (is_contains_type<float, std::decay_t<Args>...>) {
        auto&& arg_float = get_value<float>(std::forward<Args>(args)... );
        std::cout << "float is " << arg_float << "\n";
    }

}
int main()
{
    print(1, 2.5, 5.f); // 引数が右辺値の場合

    int K = 10;
    print(K); // 引数が左辺値の場合

    std::cout << "K is " << K << "\n";
}

コメントを残す

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

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


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