从枚举中选择适当的功能

时间:2017-07-04 03:25:15

标签: c++ templates c++14

假设我想要包装小型库以提高可用性。我只想包装它们;我不想触及现有代码。

例如:

template <typename T>
class vector_type_A {
    //...
};
template <typename T>
class vector_type_B {
    //...
};
template <typename T>
class vector_type_C {
    //...
};

我可以这样做来包装一个类:

enum type_e {
    Type_A, Type_B, Type_C
};

template <type_e type, typename T>
class vector_selector;

template <typename T>
class vector_selector <Type_A, T> {
public: 
    using vector = vector_type_A<T>;
};
template <typename T>
class vector_selector <Type_B, T> {
public: 
    using vector = vector_type_B<T>;
};
template <typename T>
class vector_selector <Type_C, T> {
public: 
    using vector = vector_type_C<T>;
};

template <type_e type, typename T>
using vector = typename vector_selector<type,T>::vector;

但这不包括函数,只包括类。

如何为函数编写类似的选择器?

1 个答案:

答案 0 :(得分:1)

如果我们可以部分地专门化功能模板,这将很容易,但我们不能,所以我们需要使用一个类来执行此操作。

鉴于你的功能(作为例子):

template<typename T>
int fn_type_A(vector_type_A<T> const&) {
    return 0;
}

template<typename T>
int fn_type_B(vector_type_B<T> const&) {
    return 1;
}

template<typename T>
int fn_type_C(vector_type_C<T> const&) {
    return 2;
}

你可以这样写:

template<type_e type>
struct fn_selector;

template<>
struct fn_selector<Type_A>
{
    template<typename T>
    static int fn(vector_type_A<T> const& vec) {
        return fn_type_A(vec);
    }
};

template<>
struct fn_selector<Type_B>
{
    template<typename T>
    static int fn(vector_type_B<T> const& vec) {
        return fn_type_B(vec);
    }
};

template<>
struct fn_selector<Type_C>
{
    template<typename T>
    static int fn(vector_type_C<T> const& vec) {
        return fn_type_C(vec);
    }
};

template<type_e type, typename T>
int fn(vector<type, T> const& vec) {
    return fn_selector<type>::fn(vec);
}

如果您发现您正在编写其中许多内容,则应该将它们组合到一个选择器中:

template<type_e>
struct vector_selector;

template<>
struct vector_selector<Type_A>
{
    template<typename T>
    using type = vector_type_A<T>;

    template<typename T>
    static int fn(vector_type_A<T> const& vec) {
        return fn_type_A(vec);
    }
};

template<>
struct vector_selector<Type_B>
{
    template<typename T>
    using type = vector_type_B<T>;

    template<typename T>
    static int fn(vector_type_B<T> const& vec) {
        return fn_type_B(vec);
    }
};

template<>
struct vector_selector<Type_C>
{
    template<typename T>
    using type = vector_type_C<T>;

    template<typename T>
    static int fn(vector_type_C<T> const& vec) {
        return fn_type_C(vec);
    }
};

template <type_e type, typename T>
using vector = typename vector_selector<type>::template type<T>;

template<type_e type, typename T>
int fn(vector<type, T> const& vec) {
    return vector_selector<type>::fn(vec);
}

使用C ++ 17,您可以将函数选择简化为:

template<type_e type, typename T>
int fn(vector<type, T> const& vec) {
    if constexpr (type == Type_A) {
        return fn_type_A(vec);
    } else if (type == Type_B) {
        return fn_type_B(vec);
    } else {
        static_assert(type == Type_C, "Unknown type");
        return fn_type_C(vec);
    }
}