我的一个类'成员方法作为枚举类型的参数:它为不同的枚举产生不同的副作用。我想知道是否可以使用模板作为查找表,我想到了两种可能的解决方案,但它们似乎都不起作用:
//// 1 ////
class A {
public:
enum AEnum : uint8_t { first, second, ... };
private:
template<AEnum N, typename T>
struct impl {
static void do_sth(T t) { ... };
};
template<typename T>
struct impl<first, T> {
static void do_sth(T t) { ... };
};
public:
template<typename T>
void do_sth(AEnum e, T t) {
impl<e, T>::do_sth(t);
}
}
//// 2 ////
class A {
public:
enum AEnum : uint8_t { first, second, ... };
private:
template<typename T_enum, typename T>
struct impl {
static void do_sth(T t) { ... };
};
template<typename T>
struct impl<uint8_t[2], T> { // A::first
static void do_sth(T t) { ... };
};
public:
template<typename T>
void do_sth(AEnum e, T t) {
impl<uint8_t[static_cast<uint8_t>(e) + 1u], T>::do_sth(t);
}
}
以这种方式编码是不是很糟糕?
@Oli Charlesworth
switch语句出了什么问题?
do_sth的第二个参数(T)的支持类型随e的值而变化,例如A :: first支持积分,A ::第二个STL容器,例如:
template<typename T>
void do_sth(AEnum e, T t) {
switch(e) {
case first:
std::cout << &t << std::endl;
break;
case second:
std::cout << t.data() << std::endl;
break;
default:
break;
}
A a;
a.do_sth(A::first, 0);
答案 0 :(得分:2)
你必须让AEnum arg成为do_sth的模板参数:
template<AEnum e, typename T>
void do_sth(T t) { ... }
...并将其称为a.do_sth<A::first>(0)
。
或者,您可以编写单独的函数(do_sth_integral
,do_sth_container
,...),或者,如果特定T只有一个正确的操作过程,则推导出“正确”的枚举使用元编程/重载技巧给定T的值。
例如,这是一种编写两个函数的方法,例如检测数字类型和容器类型:
//The extra dummy argument is invalid for types without a nested
//"iterator" typedef
template<typename T>
void do_sth(T t, typename T::iterator * = 0)
{
//container type code
}
//The dummy arg is invalid for types without a
//std::numeric_limits specialization
template<typename T>
void do_sth(T t,
typename boost::enable_if_c<std::numeric_limits<T>::is_specialized>::type * = 0)
{
//numeric type code
}
当然,如果您传递的是具有迭代器typedef和numeric_limits特化的T,或者两者都没有,则会失败。
如果特定T只有一个合理的动作,并且很难正确猜出哪个重载应该用于未知的T,那么你可以使用一个用户必须明确专门化的特征类,或者只需要用户专门研究“impl”或派遣类。
即使在程序运行时从未调用过代码路径,也无法编写类似3.data()
之类的函数。编译器不知道它永远不会被调用,并且在任何情况下,它都会以导致诊断错误所需的方式违反语言的类型系统。
答案 1 :(得分:1)
是的,你编码的内容没有任何意义。模板实例化在编译器时解析,而e
的值显然只在运行时知道。
switch语句出了什么问题?