namespace X {
namespace Y {
class Z {
public:
enum MyEnum { a, b, c};
};
}
}
в "рабочий класс"
class MyClass
{
typedef X::Y::Z::MyEnum MyEnum;
};
Однако при этом возникают проблемы с его использованием. В принципе моя 2005 студия понимает явное специфицирование enum:
class MyClass
{
public:
typedef X::Y::Z::MyEnum MyEnum;
void DoSomething() {
// MyEnum value = a -- так не компилируется
MyEnum value = MyEnum::a; // -- так работает
}
}
Но если пытаться использовать этот enum снаружи компилятор падает в ice:
class AnotherClass
{
void DoAnotherThing() {
MyClass::MyEnum anotherValue = MyClass::MyEnum::a; // <-- тут падает
}
}
Код привожу схематично, не уверен что в нём ошибка воспроизведётся.
Но вопрос в любом случае остаётся открытым — как правильно задать typedef для enum, желательно без нестандартных расширений языка?
Первое, что приходит на ум — внести перечисление в скоуп MyClass с помошью наследования:
class MyClass : public X::Y::Z
{
public:
void DoSomething() {
// MyEnum value = a -- так не компилируется
MyEnum value = a; // -- так работает
}
};
class AnotherClass
{
void DoAnotherThing() {
MyClass::MyEnum anotherValue = MyClass::a; // Ок
}
};
Любите книгу — источник знаний (с) М.Горький
Re[2]: typedef для enum
От:
Аноним
Дата:
19.08.09 11:34
Оценка:
Здравствуйте, Bell, Вы писали:
B>Первое, что приходит на ум — внести перечисление в скоуп MyClass с помошью наследования:
Работать будет, но идеологически неверно — "is-a" парадигма и всё такое.
Видимо придётся . Самое обидное, что почти работает. Если в студии навсети мышкой на "MyClass::MyEnum::a", то во всплывающей подсказке всё правильно пишет "X:Y:Z:a = 0", а во время компиляции ice.
Приветствую, Анонимус, вы писали:
А чем не нравится
#define a X::Y::MyEnum::a
#define b X::Y::MyEnum::b
#define c X::Y::MyEnum::c
Да и вообще насколько я понимаю — стандартный подход такой:
namespace X
{
namespace Y
{
class Z
{
public:
enum MyEnum
{
a,
#define a X::Y::MyEnum::a
b,
#define b X::Y::MyEnum::b
c
#define c X::Y::MyEnum::c
};
};
}
}
Здравствуйте, Аноним, Вы писали:
А>Хочется вытащить enum из недр: A>... А>Код привожу схематично, не уверен что в нём ошибка воспроизведётся. А>Но вопрос в любом случае остаётся открытым — как правильно задать typedef для enum, желательно без нестандартных расширений языка?
namespace X {
namespace Y {
class Z {
public:
enum MyEnum { a, b, c};
};
}
}
typedef X::Y::Z MyEnum_class;
class MyClass
{
public:
typedef MyEnum_class::MyEnum MyEnum;
void DoSomething() {
MyEnum value = MyEnum_class::a;
}
};
class AnotherClass
{
void DoAnotherThing() {
MyClass::MyEnum anotherValue = MyEnum_class::a;
}
};
[In theory there is no difference between theory and practice. In
practice there is.]
[Даю очевидные ответы на риторические вопросы]
namespace X {
namespace Y {
class Z {
public:
enum MyEnum { a, b, c};
};
}
}
class MyClass
{
public:
typedef X::Y::Z::MyEnum MyClass::MyEnum;
void DoSomething() {
MyEnum value2 = MyEnum::a;
}
};
class AnotherClass
{
typedef MyClass::MyEnum AnotherClass::MyEnum;
void DoAnotherThing() {
MyClass::MyEnum anotherValue=MyEnum::a;
}
};
так компилируется
А>Но вопрос в любом случае остаётся открытым — как правильно задать typedef для enum, желательно без нестандартных расширений языка?
а правильно ли это
Здравствуйте, Sheridan, Вы писали:
S>А чем не нравится S>
S>#define a X::Y::MyEnum::a
S>#define b X::Y::MyEnum::b
S>#define c X::Y::MyEnum::c
S>
[...skip...]
И загнать a, b, c в глобальное пространство имён, да так, что нельзя будет без undef или скобок обратиться к другим переменным и перечислениям, лежащим в других namespace, но с тем же именем?
Приветствую, Alexey F, вы писали:
AF> И загнать a, b, c в глобальное пространство имён, да так, что нельзя будет без undef или скобок обратиться к другим переменным и перечислениям, лежащим в других namespace, но с тем же именем?
Здравствуйте, Sheridan, Вы писали:
S>А анонимус разве не подобного хочет?
Да, вроде, хочет enum в другой класс перенести:
Хочется вытащить enum из недр:
[...skip...]
в "рабочий класс"
Но даже если бы хотел вытащить в глобальное, использовать для такой цели макросы, ИМХО — нецелесообразно.
Во-первых, у них могут быть очень неудобные имена (если, конечно, константы не определяются с именами в ВЕРХНЕМ регистре ). Во-вторых, уже просто так не используешь разные константы с одним именем из разных пространств имён:
#include <iostream>
#include <ostream>
// В одном include-файле:namespace Y {
namespace SomethingOther {
enum {
firstConstant = 42,
somethingOtherConstant = 42 * 2
};
namespace X {enum {
firstConstant = 43
};
}
}
}
// В другом include-файле, подключаемом после предыдущего:namespace X {
enum {
firstConstant = 0,
#define firstConstant X::firstConstant
secondConstant = 1
#define secondConstant X::secondConstant
};
}
// ...int main () {
// Думаю, здесь разработчик имел ввиду значение 42, а никак не 43, т.к. конструкция ниже развернулась
// макросом в Y::SomethingOther:: X::firstConstant.
// Главное, подмена произошла без шума, пыли и возражений компилятора, а заметить такое среди другого кода - :xz:
std::cout << Y::SomethingOther::firstConstant << std::endl;
}
А> MyEnum value = MyEnum::a; // -- так работает
А>
А вот это интересный момент g++ comeau ведут себя так как будто MyEnum:: инвалидная конструкция. При этом
struct Z
{ enum MyEnum { a, b, c};
enum MyEnum2 { a, b, c};
};
дает ошибку. Если имена констант в enum разные то он всеже не дает присвоить переменной другую константу. Единственным квалификатором является Z:: без всяких Z::MyEnum:: . Конструктор по умолчанию есть Z::MyEnum() дает 0, есть и Z::MyEnum(а) но в Z:: сам имена не ищет