Briefly: In a template that takes an enum type as parameter (not a scoped enum, a regular old pre-C++11 enum) I need to call a method, declared in the same struct as the enum, which takes an enum value as its parameter. Is there a way to do this?
In full: Suppose I'm "self-scoping" unscoped enums as follows:
struct W {
enum E { A, B, C };
static string foo(enum E e);
};
Now suppose I have a bunch of these struct declarations following this pattern - each has an enum though the enum type's name is different and each has a static method foo
taking one argument which is of that enum type.
Now I want to create a template that given a bunch of one of these enum types wants to transform each one according to its own foo()
:
template <typename E>
vector<string> xform(const vector<E> es) {
vector<string> ss;
for (E e : es) {
ss.push_back(foo(e));
}
return ss;
}
Now I instantiate xform
:
...
vector<enum W::A> as{W::A, W::C};
auto Wx = xform(as);
...
and of course I get a compiler error because the compiler can't find the right foo
to call:
prog.cc: In instantiation of 'std::vector<std::__cxx11::basic_string<char> > xform(std::vector<E>) [with E = W::A]':
prog.cc:34:24: required from here
prog.cc:24:21: error: 'foo' was not declared in this scope
24 | ss.push_back(foo(e));
| ~~~^~~
(This is all here on wandbox.)
So I need to get from the enum type to its peer method. Can I do that - how? (Since the peer method's name is always the same that part's easy - I don't know how to get from the enum type to its enclosing type.)
(Obviously I can solve this if the enum type's name in each struct is the same, by using the struct's name as the template argument. But in my use case the enums all have different names.)
Resolution (at this point): D-RAJ's answer though very simple doesn't work in this particular case because of the function foo
is not dependent on the type parameter in the template function xform
, thus the rules related to lookup and ADL and a non-dependent name in a template mean that ADL can not be used if you try to implicitly instantiate xform
in code in some other namespace. (I'm not sure I understand why, but that's the fact.) The error is that the name cannot be found at the point of template instantiation, only at the point of declaration (and only then via ADL). I guess you could get around that with explicit instantiations ... but ...
dxiv's answer of using traits works great, is not onorous, and it can be done without modifying the existing wrapped-enums at all.