Переопределение typedef после использования
От: Аноним  
Дата: 18.03.11 02:29
Оценка:
Знатоки стандарта, подскажите, пожалуйста, допустима ли следующая конструкция:
struct Base
{
    typedef int SomeType;
};
struct Derived : Base
{
    typedef SomeType BaseSomeType; // подразумевается Base::SomeType, т.к. ещё не успели переопределить
    typedef double SomeType;
};

MSVC нормально компилирует, CodePad тоже. Comeau Online ругается, но сообщение об ошибке выдаёт странное. Кто прав?
Re: Переопределение typedef после использования
От: Masterkent  
Дата: 18.03.11 03:48
Оценка:
Аноним:

А>Знатоки стандарта, подскажите, пожалуйста, допустима ли следующая конструкция:

А>
А>struct Base
А>{
А>    typedef int SomeType;
А>};
А>struct Derived : Base
А>{
А>    typedef SomeType BaseSomeType; // подразумевается Base::SomeType, т.к. ещё не успели переопределить
А>    typedef double SomeType;
А>};
А>

Так делать нельзя.

C++03 — 3.3.6/1:

2) A name N used in a class S shall refer to the same declaration in its context and when re-evaluated in the completed scope of S. No diagnostic is required for a violation of this rule.

3) If reordering member declarations in a class yields an alternate valid program under (1) and (2), the program is ill-formed, no diagnostic is required.

А>MSVC нормально компилирует, CodePad тоже. Comeau Online ругается, но сообщение об ошибке выдаёт странное. Кто прав?


Все правы, т.к. диагностика нарушения правил в данном случае не требуется.
Re[2]: Переопределение typedef после использования
От: Grim_Reaper  
Дата: 18.03.11 04:29
Оценка:
Зарегистрировался

Здравствуйте, Masterkent, Вы писали:

А>>Знатоки стандарта, подскажите, пожалуйста, допустима ли следующая конструкция:

А>>
А>>...
А>>

M>Так делать нельзя.

M>C++03 — 3.3.6/1:


Спасибо за информацию, осознал В общем, я и подозревал, что так неправильно, вот только жаль расставаться с уже работающей (в MSVC) во многих местах конструкцией... а поэтому следующий вопрос — а можно ли как-то добиться похожего поведения? Поясню в общих чертах, для чего это нужно. Это используется в некоторых макросах, которые избавляют от необходимости писать некий повторяющийся код при наследовании классов. Схема примерно такая:
struct Base
{
    typedef Base ProcessBase_;
    virtual void Process() { .../* начальная реализация */ }
};
#define OVERRIDE_PROCESS(ThisClass)  \
    typedef ProcessClass_ ProcessBase_;  \
    typedef ThisClass ProcessClass_;  \
    void Process() { .../* дополнение реализации */; ProcessBase_::Process(); }
struct Derived1 : Base
{
    OVERRIDE_PROCESS(Derived1)
};
struct Derived2 : Derived1
{
    OVERRIDE_PROCESS(Derived2)
};

Надеюсь, идея ясна — в макросе переопределяется какой-то член базового класса, но при реализации переопределения нужно сослаться на версию из базового класса. При этом жизненно важно избежать необходимости явно указывать при вызове макроса ещё и базовый класс, в этом главная проблема. На самом деле это очень упрощённая версия того, что реально используется — в полной версии переопределяются не только виртуальные функции, но и некоторые статические константы, у макроса есть дополнительные параметры — короче, через шаблоны не получается реализовать. Может кто посоветует, что тут можно предпринять?
Re[3]: Переопределение typedef после использования
От: Grim Reaper  
Дата: 18.03.11 04:34
Оценка:
Поправка, правильно так:
struct Base
{
    typedef Base ProcessClass_;
    virtual void Process() { .../* начальная реализация */ }
};
Re[3]: Переопределение typedef после использования
От: maykie Россия  
Дата: 18.03.11 08:40
Оценка:
Здравствуйте, Grim_Reaper, Вы писали:


G_R>Может кто посоветует, что тут можно предпринять?

самое простое — использовать имя базового класса. Его правда придётся в макросы пихать. И делать

struct Base
{
    typedef int SomeType;
};
struct Derived : Base
{
    typedef Base::SomeType BaseSomeType;
    typedef double SomeType;
};
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.