1

I have several nested enums similar to the following. I want to have an isValid() function defined as close as possible to the enum definition. Actual code is more verbose with multiple levels of nested namespaces and structs.

struct S
{
    enum E { V1, V2 };
    /* ????? */ bool isValid(E e) { return e==V1 || e==V2; }
};

template <typename Enum>
bool legalValue(Enum e)
{  
    return isValid(e);
}

Is it possible to make this code work without having to place isValid() in the global namespace?

Please don't comment on whether isValid() is good practice. This question is just as applicable for someone wanting to override operator<<() to be able to stream enum values meaningfully. In that case, is there any way the essence of operator<<() can be located within the body of struct S?

9
  • 1
    I'm not sure what the problem is here. Just make the isValid() function static, and change the legalValue() function to do return S::isValid(e);, and I think this should compile... Commented Jan 3, 2012 at 15:41
  • The idea is that legalValue<Enum>() should work for any enum that has an associated isValid() function. It doesn't work for enums nested with class or struct. Commented Jan 3, 2012 at 15:43
  • Try putting the enum inside a namespace, instead of a struct. This way, ADL should kick in (I have not tested it), and you should be able to call isValid no matter in where namespace the enum is declared. Commented Jan 3, 2012 at 15:44
  • 1
    Ah ok. So, more generally, you have code like struct S { enum E; bool foo(E); }; struct T { enum F; bool foo(F); };. You want a template that will do the "correct" thing given either S::E or T::F? Commented Jan 3, 2012 at 15:46
  • 1
    @paperjam: In my case, the natural home is inside a struct : Then try putting the function outside the struct, with its parameter being S::E instead of plain E. Commented Jan 3, 2012 at 15:48

4 Answers 4

4

No, you'll have to move isValid out of the struct. The enum definition can stay inside it, though.

struct S
{
    enum E { V1, V2 };
};

bool isValid(S::E e) { return e == S::V1 || e == S::V2; }

template <typename Enum>
bool legalValue(Enum e)
{
    return isValid(e);
}
Sign up to request clarification or add additional context in comments.

5 Comments

One of the OP's stipulations was "Is it possible to make this code work without having to place isValid() in the global namespace?"...
Thanks, but I was asking if there's a solution other than this.
@OliCharlesworth: and I guess the answer is no; updated the answer, although I can't cite chorus and verse from the Standard.
@paperjam: why would you want an answer other than this? Were you just hoping for another possibility since you'd already thought of this?
Because I have deeply nested structs and I want isValid() to be close to the enum definition.
3

It is not possible to find S from S::E.

If S were a namespace, Koenig lookup would find isValid even if it is not part of the global namespace, but I think that's not what you mean.

Comments

1

If this is for standard C++, i.e. for C++2011, you could forward declare the nested enumeration:

struct S { enum E: int; };

enum S::E: int { V1, V2 };
bool isValid(S::E e) { return e == S::V1 || S::V2; }

Of course, you also wouldn't need to nest the enumeration into a struct to avoid pollution of the enclosing scope: instead you'd use

enum class S { V1, V2 };
bool isValid(S e) { return e == S::V1 || S::V2; }

Using V1 or V2 unqualified would be illegal.

Comments

1

These might be technical points, but another option from making isValid global is to overload (or specialize)legalValue.

struct S
{
    enum E { V1, V2 };
    static bool isValid(E e) { return e==V1 || e==V2; }
};
bool legalValue(S::E e) { return S::isValid(e); }

template <typename Enum>
bool legalValue(Enum e) { return isValid(e); }

Another option is to make isValid a global friend. Though this differs in almost no way from it just being a free global function.

struct S
{
    enum E { V1, V2 };
    friend bool isValid(E e) { return e==V1 || e==V2; }
};
template <typename Enum>
bool legalValue(Enum e) { return isValid(e); }

Comments

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.