如何从枚举类型获取枚举值?

12
标题中的问题可能听起来很琐碎,因此我最好用一些代码来解释我想做什么...。
在C++11中,我可以这样做:
#include <iostream>

namespace X {
    enum class  FOO { A,B };
}

template <typename T> void foo(T t) { 
    if (t == T::A) { std::cout << "A"; }
}

int main() {
    foo(X::FOO::A);
}

重要的一点是模板foo不需要知道枚举在哪个命名空间中声明。我同样可以调用foo(Y::FOO::B)(前提是命名空间Y中有一个名为FOOenum class,其成员为AB)。
现在的问题是:如何使用旧式枚举(仅使用C++98)获得相同的效果?
这样做可以:
#include <iostream>

namespace X {
    enum FOO { A,B };
}

template <typename T> void foo(T t) { 
    if (t == X::A) { std::cout << "A"; }
}

int main() {
    foo(X::A);
}

但只有因为 foo 知道枚举是在什么命名空间下声明的。而且对于 Y::FOO::B 是不起作用的!(在C ++11中,如果我使用 if(t == T::A) ... 替换该行甚至使用普通的 enum 也可以正常工作)

是否有一种方法可以在不显式引用模板中的 X 的情况下,在C ++98/03中使其正常工作?

为了完整起见,在C ++98中,这个

template <typename T> void foo(T t) { 
    if (t == T::A) { std::cout << "A"; }
}

导致
error: ‘A’ is not a member of ‘X::FOO’

PS: 我不允许更改enum,并且模板必须存在于与enum不同的命名空间中。

PPS: 简单的if (t == 0)可能会起作用,但我想避免这种情况。

2个回答

6

在C++11之前,没有办法表示“这个枚举中的枚举器名称”。这就是为什么它被添加到C++11中,即使是非作用域枚举。


有没有办法从 T 中获取命名空间? - 463035818_is_not_a_number
@tobi303: 这将需要反射,但即使在C++17中我们也没有。 - Nicol Bolas
但这是否意味着在C++11之前,枚举实际上无法用作模板参数? - 463035818_is_not_a_number
无法用于什么目的?我肯定可以创建一个 vector<EnumType>。我可以将枚举值传递给任意数量的算法,这些算法会接受该值并对其执行某些操作。但您不能将枚举值传递给一个函数,然后将其与静态枚举器进行比较。但这相当罕见;我从未遇到过这种情况。 - Nicol Bolas
无法使用是指在不知道枚举值声明的确切位置的情况下无法引用枚举值。无论如何,感谢您的回答。我并不是很喜欢它,但我想我必须接受它 ;) - 463035818_is_not_a_number
通常在C++98中,我会使用额外的嵌套命名空间来模拟枚举类,例如:namespace FOO { enum Type { A, B }; } - Mark B

3

除了Nicol Bolas的回答之外,你可以使用ADL进行一种解决方法的“黑客方式”:

namespace X {
    enum FOO { A,B };
    bool IsA(FOO t)
    {
        return t == A;
    }
}

template <typename T> void foo(T t) { 
    if (IsA(t)) { std::cout << "A\n"; }
    else{std::cout << "not A\n";}
}

实时演示


不幸的是,我无法向 X 添加任何内容。然而,我没有预料到它会如此困难,所以我很高兴听取任何建议/解决方法。 - 463035818_is_not_a_number
@tobi303:“不幸的是,我不能向X中添加任何内容。” 当然可以。C++不关闭命名空间(除了保留的std)。您可以始终将任何内容注入到任何命名空间中。 - Nicol Bolas
@NicolBolas 哦,是的,当然可以;)。问题在于,我的问题中的“X”实际上是数百个不同的命名空间,所以我没有真正考虑过这一点。无论如何,对于我的真正问题,我找到了另一种解决方法,因此没有必要进一步解释它。对于这里提出的问题,这是一个不错的解决方案。 - 463035818_is_not_a_number

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