12

The question in the title may sound trivial, so I better explain with some code what I want to do...

In C++11 I can do this:

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

The important point here is that the template foo does not need to know in what namespace the enum is declared. I could as well call foo(Y::FOO::B) (provided there is a enum class called FOO in namespace Y having members A and B).

Now the question is: How to get the same with plain old enums (and only C++98 stuff)?

This works:

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

but only because foo knows in what namespace the enum is declared. And it wont work for a Y::FOO::B ! (In C++11 it also works if I replace the line with if (t == T::A) ..., even with a plain enum)

Is there a way to get this working in C++98/03 without refering to X in the template explicitly?

For the sake of completeness, in C++98, this

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

results in

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

PS: I am not allowed to change the enum and the template has to live in a different namespace than the enum.

PPS: a simple if (t == 0) would probably work, but thats something I would like to avoid

2 Answers 2

6

Until C++11, there was no way to say "the enumerator name within this enumeration". That's why it was added to C++11, even to unscoped enumerations.

Sign up to request clarification or add additional context in comments.

6 Comments

and there is no way to somehow get the namespace from T?
@tobi303: That would require reflection, which we don't have, even in C++17.
...but doesnt this mean that enums were pratically unusable as template parameters prior to C++11 ?
Unusable for what purpose? I can certainly make a vector<EnumType>. I can pass an enum value to any number of algorithms that take a value and do something with that value. What you can't do is pass an enum value to a function that is then going to compare it to a static enumerator. But that's quite rare; I've never had to do that.
unusable in the sense that you cannot refer to a value of the enum without knowing exactly where it is declared. Anyhow, thanks for the answer. I dont really like it, but I guess I will have to accept it ;)
|
3

To add to Nicol Bolas' answer, you can kind of hack your way to a solution using 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

3 Comments

unfortunately I cant add anything to X. However, I didnt expect it to be so diffucult, so I am happy about any suggestions / workarounds
@tobi303: "unfortunately I cant add anything to X." Of course you can. C++ doesn't close namespaces (except for std, which is reserved). You can always inject whatever you want into whatever namespace you want.
@NicolBolas oh yes sure ;). The problem is that what is X in my question in reality is a couple of hundreds different namespaces, so I ruled that out without really thinking about it. Anyhow for my real problem I found a different workaround so there is no point in trying to explain it further. For the question as asked here, this is a nice solution.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.