Re[3]: Visitor
От: Константин Л. Франция  
Дата: 03.09.07 20:25
Оценка: :))
Здравствуйте, c-smile, Вы писали:

[]

CS>Чем это лучше простой смены типа?


сон спокойнее

[]
Re[3]: Visitor
От: remark Россия http://www.1024cores.net/
Дата: 03.09.07 20:59
Оценка:
Здравствуйте, c-smile, Вы писали:

CS>Чем это лучше простой смены типа?


Ничем. Кому что нравится.

Вот ещё вариант:

Тут похоже на твой вариант, но не надо создавать и рушить объект — он сам сразу "2 в 1" — его можно переключать.

struct data
{
    int i;
};

struct base
{
    virtual void draw() = 0;
};

struct impl1 : base, virtual data
{
    virtual void draw()
    {
        std::cout << "impl1 " << i << std::endl;
    }
};

struct impl2 : base, virtual  data
{
    virtual void draw()
    {
        std::cout << "impl2 " << i << std::endl;
    }
};

struct last : impl1, impl2
{
};

int main()
{
    last l;
    base& b1 = static_cast<impl1&>(l);
    b1.draw();
    base& b2 = static_cast<impl2&>(l);
    b2.draw();
}




1024cores &mdash; all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re[4]: Visitor
От: remark Россия http://www.1024cores.net/
Дата: 03.09.07 21:07
Оценка: 16 (2)
Здравствуйте, remark, Вы писали:

R>Здравствуйте, c-smile, Вы писали:


CS>>Чем это лучше простой смены типа?


R>Ничем. Кому что нравится.


R>Вот ещё вариант:


А вот улучшенный вариант, с прямой поддержкой идиомы "переключение типа":

struct data
{
    int i;
};

struct base
{
    virtual void draw() = 0;
};

struct impl1 : base, virtual data
{
    virtual void draw()
    {
        std::cout << "impl1 " << i << std::endl;
    }
};

struct impl2 : base, virtual  data
{
    virtual void draw()
    {
        std::cout << "impl2 " << i << std::endl;
    }
};

struct last : impl1, impl2
{
    last() : self(static_cast<impl1*>(this)) {}

    template<typename type>
    void switch_to()
    {
        self = static_cast<type*>(this);
    }

    template<void (base::*f)()>
    void exec()
    {
        (self->*f)();
    }

    base* self;
};


int main()
{
    last l;
    l.exec<&base::draw>();
    l.switch_to<impl2>();
    l.exec<&base::draw>();
}



R>


1024cores &mdash; all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re[4]: Visitor
От: c-smile Канада http://terrainformatica.com
Дата: 03.09.07 21:11
Оценка: +2 :)
Здравствуйте, Константин Л., Вы писали:

CS>>Чем это лучше простой смены типа?


КЛ>сон спокойнее


Сон спокойнее если ты знаешь что твои конкуренты вместо головы
на подушку кладут книжку GoF.
Re[5]: Visitor
От: c-smile Канада http://terrainformatica.com
Дата: 03.09.07 21:37
Оценка:
Здравствуйте, remark, Вы писали:

CS>>>Чем это лучше простой смены типа?

R>>Ничем. Кому что нравится.

В нашем деле слово нравится есть эквивалент "технически грамотно".

R>>Вот ещё вариант:

...

1) Ты вводишь новую сущность — struct last т.е. весь существующий код
типа:
  base* pb = ... ; 
  pb->draw();

надо злостно рефакторить.

2) нужно представлять во что выливается конструкция
(self->*f)();

в рантайм.
Re[6]: Visitor
От: Erop Россия  
Дата: 04.09.07 05:55
Оценка:
Здравствуйте, c-smile, Вы писали:

CS>2) нужно представлять во что выливается конструкция

CS>
CS>(self->*f)();
CS>

CS>в рантайм.

Да ни во что она особое не выливается. Лишнее разыменование, которое хорошо конвейрезуется и парится.

Я тебе уже давно советую сделать такой рефакторинг, но ты чего-то не хочешь.

У тебя чего больше? Кода классов, которые ты хочешь "переключать", или коиентского кода?
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[6]: Visitor
От: Erop Россия  
Дата: 04.09.07 06:12
Оценка:
Здравствуйте, c-smile, Вы писали:

CS>1) Ты вводишь новую сущность — struct last т.е. весь существующий код

CS>типа:
CS>
CS>  base* pb = ... ; 
  pb->>draw();
CS>

CS>надо злостно рефакторить.

Не, просто last -- это то, что теперь будет видеть, под видом base старый код

Смотри, как можно сделать:
// Было примерно так (схема упрощённая, так как у Base может быть много наследников...
// Ко всем классам, которые надо изменить припишу слово Old
class OldBase {
public:
    virtual void Method1() = 0; // На самом деле тут есть два варианта Impl1 и Impl2

protected:
    BaseData data;
};

class OldImpl1 : public OldBase {
public:
    virtual void Method1() { data.Impl1(); }
}; 

class OldImpl2 : public OldBase {
public:
    virtual void Method1() { data.Impl2(); }
}; 

void foo( OldBase* obj )
{
    obj->Method1();
}

// а станет так

struct IBaseProcessor {
    virtual void Method( BaseData& ) = 0;
};

class CBase {
public:
    
    void Method1() { processor->Method( data ); }

protected:
    IBaseProcessor* processor;
    BaseData data;
};

struct CBasePocessorImpl1 : IBaseProcessor {
    virtual void Method( BaseData& data ) { data.Impl1(); }
};

struct CBasePocessorImpl2 : IBaseProcessor {
    virtual void Method( BaseData& data ) { data.Impl2(); }
};

foo( Base * base )
{
    base->Method1(); // вообще ничего не меняется!!!
}


Соответсвенно, реальность, скорее всего хитрее.
То есть наверное у base есть несколько наследников. И у каждого есть своя переключаемая реализация.

Ну так и это не мешает
Просто надо привинтить какую-то регистрилку процессоров, по id наследника. И уметь получать из этой регистрилки процессор под нужный тип.
Тогда ты просто статическими регистраторами регишь новую имплементацию, получаешь статический же объект, выдающий процессоры. Корорый, при переключеннии имплементации отдаёшь во все свои объекты и объекты получают из этой регистрилки свои процессоры. Ну а потом всё работает как раньше.
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[7]: Visitor
От: c-smile Канада http://terrainformatica.com
Дата: 04.09.07 06:49
Оценка:
Здравствуйте, Erop, Вы писали:

E>Я тебе уже давно советую сделать такой рефакторинг, но ты чего-то не хочешь.


Зачем?

В C++ объект это есть структура содержащая указатель на vtbl + данные инстанса.
По условию задачи мне нужно менять значение указателя vtbl
т.е. замена 1 (одного) указателя. Решается все 1 (одной) одной функцией из 5 (пяти) строк.

Я не могу понять — за ради каких вселенских принципов предлагается
1) зарефакторить 50тыс. строк кода 2) заведомо менее эффективным решением.
Re[8]: Visitor
От: Erop Россия  
Дата: 04.09.07 07:00
Оценка:
Здравствуйте, c-smile, Вы писали:

CS>Зачем?

Чтобы код был более поддерживаемым. Если у вас и так получается поддерживать 50 000 строк такого кода с хаками, ну значит и так у вас всё хорошо.
Хотя можно рефакторить по чуть-чуть. Типа переписывать классы по одному, например.

CS>В C++ объект это есть структура содержащая указатель на vtbl + данные инстанса.

CS>По условию задачи мне нужно менять значение указателя vtbl
Это всё неправда, увы. Например при множественном наследовании...
Но пока не бахает, не бахает. Просто когда бахнет прийдётся нагнуться раком и всё как-то резко поменять

CS>т.е. замена 1 (одного) указателя. Решается все 1 (одной) одной функцией из 5 (пяти) строк.

Ну надо ещё иметь шизофриническую довольно структуру "параллельных" объектов, как-то поддерживать её параллельность и т. п.
Конечно 50 000 строк -- это немного совсем кода, но всё равно совсем вручную это поддерживать уже страшновато. Лично мне было бы, во всяком случае

CS>Я не могу понять — за ради каких вселенских принципов предлагается

CS>1) зарефакторить 50тыс. строк кода 2) заведомо менее эффективным решением.
1) Потери эффективности нет
2) Надёжность и поддерживаемость. Откуда ты знаешь, что хотя бы сейчас у тебя вс работает совсем корректно?
3) Удобство отладки, в конце концов. Отладчику крышу не сносит часом?
4) Если ты займёшься каким-то более важным и нужным и новым и, скорее всего интересным, проектом, то поддержку надо будет передать кому-то ещё. ИМХО так нетрадиционно написанный код этот "кто-то ещё" будет поддерживать плохо и долго не въедет

Ну и вообще, я таки думаю, что у тебя вообще архитектура немного неудачная для твоей задачи.
Скорее всего нужен вообще заметный рефакторинг. Увы.

Но это вс вопрос бизнесстратегии. Грубо говоря сколько денег ты готов потратить на инфраструктурные инвестиции. Типа если проект будет жить ещё 10 лет и развиваться, то инфраструктурные инвестиции очень выгодны. Просто они долго очень отбиваются. А если два месяца -- то инфраструктурные инвестиции -- пустая трата сил
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[6]: Visitor
От: remark Россия http://www.1024cores.net/
Дата: 04.09.07 07:49
Оценка:
Здравствуйте, c-smile, Вы писали:

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


CS>>>>Чем это лучше простой смены типа?

R>>>Ничем. Кому что нравится.

CS>В нашем деле слово нравится есть эквивалент "технически грамотно".


"технически грамотных" может быть несколько вариантов, а дальше — кому что нравится



CS>1) Ты вводишь новую сущность — struct last т.е. весь существующий код


Можно держать указатель только на base:
    last l;
    base& b1 = static_cast<impl1&>(l);
    base& b2 = static_cast<impl2&>(static_cast<last&>((b1));


При "переключении" можно прямо из "одного" base получить "второй" base.
Про last можно забыть до удаления, а можно и вообще, т.к. при удалении можно тоже по base восстановить last.


1024cores &mdash; all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re: хочу странного: сменить класс объекта в runtime
От: StevenIvanov США  
Дата: 04.09.07 07:56
Оценка: 28 (1)
Здравствуйте, c-smile, Вы писали:

CS>...


Может я и чего то не понимаю в этой куче решений, но по моему здесь усиленно изобретают термоядерный велосипед из шаблонов и посетителей.
Ведь эта задача решается элементарно средствами С — если программишь на MSVC(или даже G++, но только не Borland C++) — можно видеть однозначное (вроде даже задокументированное) соответсвие С-шных структур С++ классам (интерфейсам).
Вот, к примеру:
#if defined(__cplusplus) && !defined(CINTERFACE)
    IXMLElement : public IDispatch
    {
    public:
        virtual HRESULT STDMETHODCALLTYPE get_tagName( BSTR *p) = 0;
    // ...
    };
    
#else     /* C style interface */

    typedef struct IXMLElement2Vtbl
    {
        BEGIN_INTERFACE
        /* IUnknown + IDispatch vtbl skipped*/
        

        HRESULT ( STDMETHODCALLTYPE *get_tagName )( IXMLElement2 * This, BSTR *p);
        
        /* ... */
        
        END_INTERFACE
    } IXMLElement2Vtbl;

    interface IXMLElement2
    {
        CONST_VTBL struct IXMLElement2Vtbl *lpVtbl;
    };
#endif

Если у тебя подобные классы, то проблем с заменой vtbl не должно быть никаких, а вот если у тебя виртуальное наследование со всякими рюшками то тогда
Re[2]: хочу странного: сменить класс объекта в runtime
От: remark Россия http://www.1024cores.net/
Дата: 04.09.07 08:14
Оценка: 14 (1)
Здравствуйте, StevenIvanov, Вы писали:

SI>Здравствуйте, c-smile, Вы писали:


CS>>...


SI>Может я и чего то не понимаю в этой куче решений, но по моему здесь усиленно изобретают термоядерный велосипед из шаблонов и посетителей.


Если на это положиться, то можно просто перезаписывать vptr, даже никакого С не надо:

struct base
{
    int i;
    virtual void draw() = 0;
};

struct d1 : base
{
    virtual void draw()
    {
        std::cout << "d1 " << i << std::endl;
    }

    static d1 instance;
};

struct d2 : base
{
    virtual void draw()
    {
        std::cout << "d2 " << i << std::endl;
    }

    static d2 instance;
};

d1 d1::instance;
d2 d2::instance;

int main()
{
    d1 d;
    base& b = d;
    b.draw();
    *reinterpret_cast<void**>(&b) = *reinterpret_cast<void**>(&d2::instance);
    b.draw();
}




1024cores &mdash; all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re[3]: хочу странного: сменить класс объекта в runtime
От: Erop Россия  
Дата: 04.09.07 08:21
Оценка:
Здравствуйте, remark, Вы писали:

R>Если на это положиться, то можно просто перезаписывать vptr, даже никакого С не надо:


Всё равно отсанется необходимость в ручном поддержании "эквивалентности" различных реализаций
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[8]: Visitor
От: Константин Л. Франция  
Дата: 04.09.07 09:36
Оценка:
Здравствуйте, c-smile, Вы писали:

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


E>>Я тебе уже давно советую сделать такой рефакторинг, но ты чего-то не хочешь.


CS>Зачем?


CS>В C++ объект это есть структура содержащая указатель на vtbl + данные инстанса.

CS>По условию задачи мне нужно менять значение указателя vtbl
CS>т.е. замена 1 (одного) указателя. Решается все 1 (одной) одной функцией из 5 (пяти) строк.

ну так давно пора закрыть ветку, раз ты все для себя решил.

CS>Я не могу понять — за ради каких вселенских принципов предлагается

CS>1) зарефакторить 50тыс. строк кода 2) заведомо менее эффективным решением.

А я не могу понять, почему ты так относишься к предложениям, которые выдвигаются по твоей собственной просьбе? Зачем все в штыки принимать?
Re[9]: Visitor
От: c-smile Канада http://terrainformatica.com
Дата: 04.09.07 16:14
Оценка:
Здравствуйте, Константин Л., Вы писали:

CS>>В C++ объект это есть структура содержащая указатель на vtbl + данные инстанса.

CS>>По условию задачи мне нужно менять значение указателя vtbl
CS>>т.е. замена 1 (одного) указателя. Решается все 1 (одной) одной функцией из 5 (пяти) строк.

КЛ>ну так давно пора закрыть ветку, раз ты все для себя решил.


Да пора.

CS>>Я не могу понять — за ради каких вселенских принципов предлагается

CS>>1) зарефакторить 50тыс. строк кода 2) заведомо менее эффективным решением.

КЛ>А я не могу понять, почему ты так относишься к предложениям, которые выдвигаются по твоей собственной просьбе? Зачем все в штыки принимать?


Мда, народ упорно не читает ТЗ.
Вопрос был такой "Существует ли способ сменить класс объекта в p?"
Все.
Re[10]: Visitor
От: Erop Россия  
Дата: 04.09.07 16:17
Оценка:
Здравствуйте, c-smile, Вы писали:

CS>Мда, народ упорно не читает ТЗ.

CS>Вопрос был такой "Существует ли способ сменить класс объекта в p?"
CS>Все.
Ну тебе предлагали разные решения на эту тему.
Например, я
Автор: Erop
Дата: 01.09.07
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[4]: хочу странного: сменить класс объекта в runtime
От: c-smile Канада http://terrainformatica.com
Дата: 04.09.07 16:37
Оценка:
Здравствуйте, Erop, Вы писали:

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


R>>Если на это положиться, то можно просто перезаписывать vptr, даже никакого С не надо:


E>Всё равно отсанется необходимость в ручном поддержании "эквивалентности" различных реализаций


Что такое "ручное поддержании эквивалентности" в твоем понимании?

class P 
{
  virtual int foo() = 0;
}

class A 
{
  virtual int foo() { ... 1 }
}

class B 
{
  virtual int foo() { ... 2 }
}



Это вот "ручное" или нет?
Re[5]: хочу странного: сменить класс объекта в runtime
От: Erop Россия  
Дата: 04.09.07 16:40
Оценка:
Здравствуйте, c-smile, Вы писали:

CS>Что такое "ручное поддержании эквивалентности" в твоем понимании?


CS>
CS>class P 
CS>{
CS>  virtual int foo() = 0;
CS>}

CS>class A 
CS>{
CS>  virtual int foo() { ... 1 }
CS>}

CS>class B 
CS>{
CS>  virtual int foo() { ... 2 }
CS>}
CS>



CS>Это вот "ручное" или нет?


Я так понимаю, что обычно жизнь немного не такая.
1) методов много
2) Есть данные. Они должны быть одинаковыми везде, вроде как. Или ты выводишь свои "стратегии" из реального класса с данными?
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[10]: Visitor
От: remark Россия http://www.1024cores.net/
Дата: 04.09.07 16:42
Оценка: +2
Здравствуйте, c-smile, Вы писали:

КЛ>>А я не могу понять, почему ты так относишься к предложениям, которые выдвигаются по твоей собственной просьбе? Зачем все в штыки принимать?


CS>Мда, народ упорно не читает ТЗ.

CS>Вопрос был такой "Существует ли способ сменить класс объекта в p?"
CS>Все.

Просто все подумали, что ответ "нет" очевиден, и что он очевиден и тебе Поэтому додумали твою проблему, и предлагают решения. Вот.


З.ы. "хакерское" создание нового объекта на месте старого — не смена типа *объекта*


1024cores &mdash; all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re[10]: Visitor
От: Константин Л. Франция  
Дата: 04.09.07 17:07
Оценка:
Здравствуйте, c-smile, Вы писали:

[]

CS>Мда, народ упорно не читает ТЗ.

CS>Вопрос был такой "Существует ли способ сменить класс объекта в p?"
CS>Все.

не хочется флеймить, но ты упорно пытаешься "продвинуть" свой вариант с placement new, выдвигая аргумент "зачем", вместо того, чтобы рассмотреть все плюсы и минусы. Не безопасен он. Как только размеры объектов изменятся, ты получишь вылет в корку, а не compile-time error/warning.
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.