枚举作为模板

5
这是我想要做的事情:
enum MyEnum
{
    ONE = 1, TWO, THREE
};

template<class T>
void func()
{
    cout << T::TWO << endl;
}

int main()
{
    func<MyEnum>();
};

代码可以正常工作,但我收到了一个警告:"warning C4482: nonstandard extension used: enum 'MyEnum' used in qualified name"。

我该如何在不收到警告的情况下进行操作?


1
enum E1 { ONE, TWO }; enum E2 { ONE, TWO }; 这段代码会出现 “ONE 冲突声明”的错误,因为 enum E1 中的值并没有进入命名空间 E1。你期望会发生什么呢? - user395760
1
您的 MyEnum 中定义了 TWO,但它不是您所展示的类或命名空间的一部分。枚举不声明作用域,因此不能使用作用域运算符进行解析。 - Zac Howland
但这就是我想做的,我希望能够传递E1和E2并在打印时获得不同的值。 - hidayat
那么你需要使用 classstruct,而不是 enum - Zac Howland
你使用哪个编译器?我见过的几乎所有 G++ 编译器(Linux 和 OSX)都会在 T::TWO 处产生错误。 - Foo Bah
3个回答

5

在这里,枚举类型有点棘手。类型ONE和TWO将位于外部命名空间中。因此,将类型添加到名称中会导致警告。您可以只删除限定符。

template<class T>
void func()
{
    cout << TWO << endl;
}

由于TWO在外部命名空间中已知。

您也可以将枚举移动到某种封闭结构中。

struct EnumContainer
{
    enum MyEnum
    {
        ONE = 1, TWO, THREE
    };
};

template<class T>
void func()
{
    std::cout << T::TWO << std::endl;
}

int main()
{
    func<EnumContainer>();
};

现在编译器应该没问题了。

类型 ONE 和 TWO 将在外部命名空间中。请注意,它们是枚举类型,而不是类型,根据标准规范。 - Tony Delroy
2
在C++中,你可以使用enum struct MyEnum { ONE, TWO };来定义强类型枚举,详情请见http://en.wikipedia.org/wiki/C%2B%2B0x#Strongly_typed_enumerations。 - Matthieu M.

1

虽然使用枚举作为模板参数并让它识别你所编写的每个单独的枚举会很好,但这不可能发生。相反,我建议您声明以下内容:

template<MyEnum T>
void func(){
    std::cout << T << std::endl;
}

C++的优点在于模板的结构使得你拥有了一个图灵完备系统。因此,你不需要像这样单独调用,因为你已经声明了获取每个枚举值的方式。当你需要时,你可以为每个值创建一个单独的函数仅在需要时

现在,回到你问题的另一个问题,正如@delnan所评论的那样,你不能有两个不同的枚举具有相同的名称。但是,你可以有一个类,其中包含一个名为TWO的成员变量,例如:

struct Foo{
    int TWO;
};

struct Bar{
    int TWO;
};

template<typename T>
void func(){
    std::cout << T::TWO << std::endl;
}

希望这有所帮助。

他也可以将枚举声明为结构体的成员,这样他就可以在不同的作用域中定义枚举(多次定义)。尽管在大多数情况下我会质疑为什么这样做是可取的。 - Zac Howland
我怀疑这段代码能否编译通过。typename 用于类型,而 TWO 是一个需要类的实例的属性... - Matthieu M.

1

枚举类型(C++0x之前)被视为整数类型。

事实上,表示法MyEnum :: TWO是无效的:没有类或名称空间MyEnum。名称ONE、TWO和THREE被带入定义枚举的名称空间中[在这种情况下,全局名称空间]。

您应该收到像“TWO不是MyEnum的成员”的错误。

模仿此行为的一种方法是将其放入结构或类中,就像其他人建议的那样。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接