我有一个template class
使用enum class
作为模板参数,在头文件中定义:
// MyClass.h
enum class MyEnum {FOO, BAR};
template<MyEnum T>class MyClass {
void doStuff();
// ...
};
我希望将成员函数的实际实现放在单独的源文件中。我知道,在这种情况下,我必须为每种情况强制执行模板的初始化:
//MyClass.cpp
template<MyEnum T>void MyClass<T>::doStuff() {
// ...
}
// Implementations of other functions
template class MyClass<MyEnum::FOO>;
template class MyClass<MyEnum::BAR>;
通常情况下,我知道我需要{{1>}的所有可能值的类,所以我想告诉编译器它应该为每个实际构建模板类可能的值没有明确提及每种可能性。
换句话说:我想用一些自动代码替换示例中的最后两行。
这有可能吗?
我也想对模板函数而不是模板类做同样的事情。
答案 0 :(得分:1)
让编译器了解所有可能的特化的常用方法是在同一个文件中实现它们。我想不出一种理智的方式让编译器知道模板类专门用于域中的每个值。
如果你有大量的,你可以考虑使用X macro pattern。将所有案例隔离在头文件中(例如MyEnum.h
),如下所示:
#ifndef HANDLE_ENUM_CASE(e)
#define HANDLE_ENUM_CASE(e)
#endif
HANDLE_ENUM_CASE(FOO)
HANDLE_ENUM_CASE(BAR)
// add more HANDLE_ENUM_CASE(...) expressions for every other case you have
#undef HANDLE_ENUM_CASE
在源文件中,您可以拥有:
enum class MyEnum {
#define HANDLE_ENUM_CASE(e) e,
#include "MyEnum.h"
}
// (class declaration here)
#define HANDLE_ENUM_CASE(e) template class MyClass<MyEnum::e>;
#include "MyEnum.h"
答案 1 :(得分:0)
在过去,枚举只是整数值的自定义名称,这很简单:我们只是添加了一个MAX值作为最后一个枚举,并仅用for (int i=0; i<MAX; i++)
进行迭代。
如果你使用简单的enum MyEnum { FOO, BAR };
,你至少可以将一个MyEnum强制转换成一个int,(但不是相反,太容易了)。但是对于int的enum class MyEnum { FOO, BAR };
转换也没有定义。
所以唯一的C ++ 11枚举方式是...... zneak提出的宏观方法......嗅探: - (
如果您不喜欢(我不),您必须忘记enum class
并使用普通整数,或者至少使用typedef。并非全部,非类型模板参数必须是常量表达式,因此您还应该忘记非类型模板构造。
这会导致:
namespace MyEnum {
typedef int MyEnum_t;
enum MyEnum : MyEnum_t { FOO, BAR, MAX };
}
class MyClass {
MyEnum::MyEnum_t T;
public:
MyClass(MyEnum::MyEnum_t t): T(t) {}
void doStuff() {
std::cout << T << std::endl;
}
};
您应该声明一个复制构造函数,以确保您只在兼容类型之间进行复制,因为编译器无法再控制它。但至少你能做到:
for(MyEnum::MyEnum_t e=0; e<MyEnum::MAX; e++) {
MyClass obj(e);
obj.doStuff();
}
BTW,因为MyClass
不再是模板,你可以安全地将成员函数的实际实现放在一个单独的源文件中......