Операции C ++ над вложенными перечислениями - PullRequest
1 голос
/ 03 января 2012

У меня есть несколько вложенных перечислений, похожих на следующие. Я хочу, чтобы функция isValid() была определена как можно ближе к определению enum. Фактический код более многословен с несколькими уровнями вложенных пространств имен и структур.

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

Можно ли заставить этот код работать, не помещая isValid() в глобальное пространство имен?

Пожалуйста, не комментируйте, является ли isValid() хорошей практикой. Этот вопрос так же применим к тому, кто хочет переопределить operator<<(), чтобы иметь возможность целенаправленно передавать значения перечисления. В таком случае, может ли сущность operator<<() находиться внутри тела struct S?

?

Ответы [ 4 ]

4 голосов
/ 03 января 2012

Нет, вам придется вывести isValid из struct. Однако определение enum может оставаться внутри него.

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);
}
3 голосов
/ 03 января 2012

Невозможно найти S из S::E.

Если бы S было пространством имен, Поиск Кенига нашел бы isValid, даже если оно не является частью глобального пространства имен, но я думаю, это не то, что вы имеете в виду.

1 голос
/ 04 января 2012

Это могут быть технические моменты, но другой способ сделать глобальный isValid - это перегрузить (или специализировать) 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); }

Другой вариант - сделать isValid глобальным другом. Хотя это почти ничем не отличается от простой глобальной функции.

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); }
1 голос
/ 04 января 2012

Если это для стандартного C ++, то есть для C ++ 2011, вы можете переслать объявление вложенного перечисления:

struct S { enum E: int; };

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

Конечно, вам также не нужно будет вкладывать перечисление в структуручтобы избежать загрязнения окружающей области: вместо этого вы бы использовали

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

Использование V1 или V2 без оговорок было бы незаконным.

...