简体   繁体   English

我可以强制初始化枚举类类/函数模板的所有可能的枚举值吗?

[英]Can I force initialization for all possible enum values of an enum class class/function template?

I have a template class using an enum class as template parameter, defined in a header file: 我有一个template class使用enum class作为模板参数,在头文件中定义:

// MyClass.h
enum class MyEnum {FOO, BAR};

template<MyEnum T>class MyClass {
  void doStuff();
  // ...
};

I would like to have the actual implementations of the member functions in a separate source file. 我想在单独的源文件中具有成员函数的实际实现。 I know, that in that case I have to enforce the initialization of the template for each case: 我知道,在这种情况下,我必须为每种情况强制执行模板的初始化:

//MyClass.cpp
template<MyEnum T>void MyClass<T>::doStuff() {
  // ...
}
// Implementations of other functions

template class MyClass<MyEnum::FOO>;
template class MyClass<MyEnum::BAR>;

Typically, I know that I need the class with all possible values for the enum anyway, so I would like to tell the compiler that it should actually build the template class for each possible value without explicitly mentioning each possibility . 通常,我知道我需要具有enum 所有可能值的类,所以我想告诉编译器它应该为每个可能的值实际构建模板类, 而没有明确提到每种可能性

In other words: I want to replace the last two lines in the example by some automated code. 换句话说:我想用一些自动代码替换示例中的最后两行。

Is this somehow possible? 这有点可能吗?

I would also like to do the same with template functions instead of a template class. 我也想对模板函数而不是模板类做同样的事情。

The normal way to let the compiler know about all the possible specializations is to implement them in the same file. 让编译器了解所有可能的特化的常用方法是在同一个文件中实现它们。 I can't think of a sane way to let the compiler know that a template class is specialized for every value in the domain. 我想不出一种理智的方式让编译器知道模板类专门用于域中的每个值。

If you have a bazillion of them, you could consider using the X macro pattern . 如果你有很多,你可以考虑使用X宏模式 Isolate all your cases in a header file (say MyEnum.h ) like that: 将所有案例隔离在头文件(例如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

In your source file, you can then have: 在源文件中,您可以拥有:

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"

In the old days when enum were just custom names for integer values, it was trivial : we just added a MAX value as the last enum and iterated with a mere for (int i=0; i<MAX; i++) . 在enum只是整数值的自定义名称的过去,它是微不足道的:我们只是添加一个MAX值作为最后一个枚举,并仅仅for (int i=0; i<MAX; i++)迭代。

If you were using a simple enum MyEnum { FOO, BAR }; 如果您使用简单的enum MyEnum { FOO, BAR }; you could at least cast a MyEnum to an int, (but not the opposite, would be too easy). 你至少可以把一个MyEnum强制转换成一个int,(但不是相反的,太简单了)。 But with a enum class MyEnum { FOO, BAR }; 但是有一个enum class MyEnum { FOO, BAR }; casting to an int is no defined either. 转换为int也没有定义。

So the only C++11 enum way is ... the macro way proposed by zneak ... sniff :-( 所以唯一的C ++ 11枚举方式是...... zneak提出的宏观方式......嗅探:-(

If you do not like that ( I don't ) you have to forget enum class and use plain integers, or at least as typedef. 如果您不喜欢( 我没有 ),您必须忘记enum class并使用普通整数,或者至少使用typedef。 And it is not all, a non-type template argument must be a constant expression, so you should also forget the non-type template construct. 并非全部,非类型模板参数必须是常量表达式,因此您还应该忘记非类型模板构造。

It would lead to : 这会导致:

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

You should probably declare a copy constructor that makes sure that you only copy between compatible types, because the compiler can no longer control it. 您应该声明一个复制构造函数,以确保您只在兼容类型之间进行复制,因为编译器无法再控制它。 But as least you could do : 但至少你可以做到:

for(MyEnum::MyEnum_t e=0; e<MyEnum::MAX; e++) {
    MyClass obj(e);
    obj.doStuff();
}

BTW, as MyClass would no longer be a template, you could safely put the actual implementations of the member functions in a separate source file... 顺便说一下,由于MyClass不再是模板,你可以安全地将成员函数的实际实现放在一个单独的源文件中......

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM