【问题标题】:how to get enum value from enum type?如何从枚举类型中获取枚举值?
【发布时间】:2017-07-25 15:09:59
【问题描述】:

标题中的问题可能听起来微不足道,所以我最好用一些代码来解释我想要做什么......

在 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)(前提是enum class 在命名空间Y 中有一个名为FOO 的成员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,它也可以工作)

有没有办法让它在 C++98/03 中工作而无需在模板中明确引用 X

为了完整起见,在 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) 可能会起作用,但这是我想避免的事情

【问题讨论】:

    标签: c++ enums c++03


    【解决方案1】:

    在 C++11 之前,没有办法说“此枚举中的枚举数名称”。这就是为什么它被添加到 C++11 中,甚至添加到了无作用域的枚举中。

    【讨论】:

    • 没有办法从T获取命名空间?
    • @tobi303:这需要反射,我们没有,即使在 C++17 中也是如此。
    • ...但这是否意味着枚举在 C++11 之前实际上无法用作模板参数?
    • 不能用于什么目的?我当然可以做一个vector&lt;EnumType&gt;。我可以将枚举值传递给任意数量的算法,这些算法采用一个值并使用该值执行某些操作。你不能做的是将枚举值传递给一个函数,然后将它与一个静态枚举器进行比较。但这很少见。我从来没有这样做过。
    • 无法使用,因为您无法在不知道枚举的确切声明位置的情况下引用枚举的值。无论如何,谢谢你的回答。我不太喜欢它,但我想我将不得不接受它;)
    【解决方案2】:

    要添加到Nicol Bolas' answer,您可以使用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";}
    }
    

    Live Demo

    【讨论】:

    • 很遗憾,我无法向X 添加任何内容。但是,我没想到它会如此困难,所以我很高兴有任何建议/解决方法
    • @tobi303:“很遗憾,我无法向 X 添加任何内容。”当然可以。 C++ 不会关闭命名空间(std 除外,它是保留的)。你可以总是将你想要的任何东西注入你想要的任何命名空间。
    • @NicolBolas 哦,是的,当然;)。问题是我的问题中的X 实际上是数百个不同的命名空间,所以我在没有真正考虑的情况下排除了这一点。无论如何,对于我真正的问题,我找到了一个不同的解决方法,所以没有必要进一步解释它。对于这里提出的问题,这是一个很好的解决方案。
    猜你喜欢
    • 2017-01-14
    • 1970-01-01
    • 1970-01-01
    • 2018-10-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多