从枚举中选择适当的函数

Select appropriate function from enum

本文关键字:函数 选择 枚举      更新时间:2023-10-16

假设我有一个小库,我想包装它以提高可用性。我只想包装它们;我不想碰现有的代码。

例如:

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;

但这不会包装函数,只包装类。

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

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

给定您的函数(例如(:

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