Модераторы: Daevaorn

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Трюк, возможно ли это? 
:(
    Опции темы
mes
Дата 9.9.2008, 02:28 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 144
Всего: 250



Цитата(vaddsm @  9.9.2008,  01:20 Найти цитируемый пост)
Ага, поставьте +

Цитата(mes @  9.9.2008,  00:53 Найти цитируемый пост)
+1

уже поставил )


--------------------
PM MAIL WWW   Вверх
Lazin
Дата 9.9.2008, 05:38 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3820
Регистрация: 11.12.2006
Где: paranoid oil empi re

Репутация: 41
Всего: 154



Цитата(xvr @  8.9.2008,  18:30 Найти цитируемый пост)
Жуть конечно, но гораздо более переносимо, чем asm вставки 

ничего не заметили? smile 
PM MAIL Skype GTalk   Вверх
mes
Дата 9.9.2008, 09:13 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 144
Всего: 250



Цитата(Lazin @  9.9.2008,  05:38 Найти цитируемый пост)
ничего не заметили? smile  

ага, заметили.. ) никто и не оспаривает реальное его "жутие", однако это не преуменьшает заслуги xvr'a,
показавшего пример, который отвечает на вопрос темы. 


Это сообщение отредактировал(а) mes - 9.9.2008, 09:47


--------------------
PM MAIL WWW   Вверх
vaddsm
Дата 9.9.2008, 11:05 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 128
Регистрация: 30.6.2007

Репутация: нет
Всего: нет



А жутие то в чем собственно? Чес слово, вот на asm - то действительно было жутие. Не тебе стандартов, не тебе переносимости. Мне бы хотелось понять каким критериям не удовлетворяет данный код?
PM MAIL   Вверх
vinter
Дата 9.9.2008, 11:15 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Explorer
****


Профиль
Группа: Завсегдатай
Сообщений: 2735
Регистрация: 1.4.2006
Где: Н.Новгород

Репутация: 13
Всего: 56



Цитата(vaddsm @  9.9.2008,  12:05 Найти цитируемый пост)
 Мне бы хотелось понять каким критериям не удовлетворяет данный код?

читабельности


--------------------
Мой блог
PM MAIL WWW   Вверх
vaddsm
Дата 9.9.2008, 11:18 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 128
Регистрация: 30.6.2007

Репутация: нет
Всего: нет



Good
  • 1. читабельности
  • 2.


Продолжите список, пожалуйста.
PM MAIL   Вверх
vinter
Дата 9.9.2008, 11:34 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Explorer
****


Профиль
Группа: Завсегдатай
Сообщений: 2735
Регистрация: 1.4.2006
Где: Н.Новгород

Репутация: 13
Всего: 56



Цитата

Because of the extended functionality of structs in C++, in this language, the use of offsetof is restricted to "POD types", which for classes, more or less corresponds to the C concept of struct (although non-derived classes with only public non-virtual member functions and with no constructor and/or destructor would also qualify as POD).

хм, получается что этот макрос на честном слове работает в этом случае?


--------------------
Мой блог
PM MAIL WWW   Вверх
vaddsm
Дата 9.9.2008, 12:23 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 128
Регистрация: 30.6.2007

Репутация: нет
Всего: нет



Гляньте, как описан в различных компиляторах данный макрос:

Код

// Keil 8051 compiler
#define offsetof(s,m) (size_t)&(((s *)0)->m) 

// Microsoft x86 compiler (version 7)
#define offsetof(s,m) (size_t)(unsigned long)&(((s *)0)->m) 

// Diab Coldfire compiler
#define offsetof(s,memb) ((size_t)((char *)&((s *)0)->memb-(char *)0))


В борланде, первый вариант применяется. Решительно не понимаю, как подобная вешь может быть интерпретирована не правильно. Если компилятор всегда знает смещения членов класса (относительно начала класса), как подобный макрос может привести к ошибке? У меня работает верно и при наследовании и для абстрактных классов.

Гляньте статью, здесь рассмотрены другие варианты примененя этого макроса, ни слова о несовместимости с ПОД типами. http://www.embedded.com/columns/technicali...equestid=142048
PM MAIL   Вверх
Lazin
Дата 9.9.2008, 12:25 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3820
Регистрация: 11.12.2006
Где: paranoid oil empi re

Репутация: 41
Всего: 154



Цитата

А жутие то в чем собственно? Чес слово, вот на asm - то действительно было жутие. Не тебе стандартов, не тебе переносимости. Мне бы хотелось понять каким критериям не удовлетворяет данный код?
  • он неясный, "explicit is better then implicit" и в том-же духе...
  • это не в стиле С++
  • макросы для изменения кода лучше не использовать, их принято использовать только для управления компиляцией, а не в качестве замены шаблонов
  • call_whatever_you_need - вызывается в то время, когда объект еще не сконструирован, то-есть функция будет вызвана тогда, когда для некоторых членов класса еще не-был вызван конструктор, единственный способ это обойти, размещать твой макрос в теле класса до объявления членов класса
я уже предлагал написать для пользовательского класса враппер, предложу еще раз,
допустим есть пользовательский класс:
Код

class my_test
{
public:
    int a_;
    std::string b_;
    my_test(int a, std::string& b) : a_(a), b_(b) {}
    std::string name()
    {
        return std::string("third");
    }
};

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

template<class T, class P, P T::*Value>
struct class_member
{
    static P& get(T& self)
    {
        return self.*Value;
    }
};

функция get шаблона получает this и возвращает требуемый член класса, то-же самое можно сделать и для функций:
Код

template<class T, class P, P (T::*Fn)()>
struct class_member_fn
{
    static P call(T& self)
    {
        return (self.*Fn)();
    }
};

этот класс - для функций без параметров, но можно сделать и с параметрами...
теперь код самого враппера:
Код

template<class Derived, class Member>
class wrapper : public Derived
{
public:
    wrapper() : Derived() {}

    template <class P>
    wrapper(P p) : Derived(p) {print_base_member();}

    template <class P1, class P2>
    wrapper(P1 p1, P2 p2) : Derived(p1, p2) {print_base_member();}

    template <class P1, class P2, class P3>
    wrapper(P1 p1, P2 p2, P3 p3) : Derived(p1, p2, p3) {print_base_member();}

    template <class P1, class P2, class P3, class P4>
    wrapper(P1 p1, P2 p2, P3 p3, P4) : Derived(p1, p2, p3, p4) {print_base_member();}

    void print_base_member()
    {
        std::cout << Member::get(static_cast<Derived&>(*this)) << std::endl;
    }
};

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

typedef wrapper<
            my_test, 
            class_member<my_test, int, &my_test::a_> 
> wrap_test;

то компилятор сгенерирует класс, который ведет себя так-же как и пользовательский, но при создании его экземпляра будет выполнен нужный нам код (в данном случае будет выведено значение члена класса, который передан в качестве параметра), так-же, в отличии от кода с макросами, врапперы можно объединять в цепочки и работать с произвольным набором параметров...
Код

typedef wrapper<
            wrap_test, 
            class_member<my_test, std::string, &my_test::b_> 
> double_wrap_test;

при создании экземпляра класса double_wrap_test будут выведены на экран оба члена класса my_test, далее, можно написать враппер для функций:
Код

template<class Derived, class Function>
class wrapper_fn : public Derived
{
public:
    wrapper_fn() : Derived() {}

    template <class P>
    wrapper_fn(P p) : Derived(p) {print_base_member();}

    template <class P1, class P2>
    wrapper_fn(P1 p1, P2 p2) : Derived(p1, p2) {print_base_member();}

    template <class P1, class P2, class P3>
    wrapper_fn(P1 p1, P2 p2, P3 p3) : Derived(p1, p2, p3) {print_base_member();}

    template <class P1, class P2, class P3, class P4>
    wrapper_fn(P1 p1, P2 p2, P3 p3, P4) : Derived(p1, p2, p3, p4) {print_base_member();}

    void print_base_member()
    {
        std::cout << Function::call(static_cast<Derived&>(*this)) << std::endl;
    }
};

который вызывает функцию пользовательского класса, если сделать так:
Код

typedef wrapper_fn<
            double_wrap_test,
            class_member_fn<my_test, std::string, &my_test::name>
> thriple_wrap_test;

то после создания объекта my_test, будут выведены параметры a_, потом b_, а потом то, что вернет функция name...
так-же можно перехватить момент удаления объекта, и самое приятное в этом, что компилятор теперь сам будет следить за корректностью кода, если я попытаюсь создать объект у которого конструктор принимает больше 4х параметров, код просто не скомпилируется, а не упадет....
когда работает код враппера, все данные пользовательского класса уже гарантировано сконструированы....

Добавлено через 13 минут и 57 секунд
Цитата

call_whatever_you_need - вызывается в то время, когда объект еще не сконструирован, то-есть функция будет вызвана тогда, когда для некоторых членов класса еще не-был вызван конструктор, единственный способ это обойти, размещать твой макрос в теле класса до объявления членов класса
вот тут я наврал, нужно размещать макрос не до объявления а после, так как переменные класса конструируются в порядке их объявления...
PM MAIL Skype GTalk   Вверх
vinter
Дата 9.9.2008, 14:09 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Explorer
****


Профиль
Группа: Завсегдатай
Сообщений: 2735
Регистрация: 1.4.2006
Где: Н.Новгород

Репутация: 13
Всего: 56



vaddsm, я честно говоря не совсем понимаю что написано в том предложении, оно какое то кривое. Но насколько я понял, там имеется ввиду, что ограничен в рабе с НЕ POD типами.. эта сцитата с C++ references, и я не вижу причин им не доверять. По всей видимости это несовсем\совсем не стандартная фича. Жаль стандарта нет под рукой...


--------------------
Мой блог
PM MAIL WWW   Вверх
mes
Дата 9.9.2008, 14:21 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 144
Всего: 250



Цитата(vaddsm @  9.9.2008,  11:05 Найти цитируемый пост)
Мне бы хотелось понять каким критериям не удовлетворяет данный код? 

вот пример опасного кода:

Код

class A
{
    public:

       A () : i(2) {}
       void f ()  { std::cout<<"A::f() "<<i << endl;  }
    private:
        int i;
};

class Test  {
public:
TABLE_DEF(Test)

 void call_whatever_you_need() { std::cout<<"call_... "<<i << endl;  p->f(); }

 Test() : i (5), p(new A) { }

 private:
  int i;
  A *p;
};





Это сообщение отредактировал(а) mes - 9.9.2008, 15:17


--------------------
PM MAIL WWW   Вверх
xvr
Дата 9.9.2008, 15:05 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 7046
Регистрация: 28.8.2007
Где: Дублин, Ирландия

Репутация: 60
Всего: 223



Цитата(mes @ 9.9.2008,  14:21)
Цитата(vaddsm @  9.9.2008,  11:05 Найти цитируемый пост)
Мне бы хотелось понять каким критериям не удовлетворяет данный код? 

вот пример опасного кода:

Код

class A
{
   public: 
    void f() { std::cout << "test"; }
}
class Test  {
public:

TABLE_DEF(Test)
 void call_whatever_you_need() { p_a->f();};

 Test() : p_a (new A) { }
 ~Test() { delete p_a; }

 private:
  A* p_a;
};


сам не тестировал(ухожу потому что.. вернусь попробую), но по правилам языка поведение в таком случае неопределено.

Вполне определено - Segmentation Fault  smile Большие грабли этого метода (не считая использования offsetof) это требование размещать макрос TABLE_DEF после описания всех остальных полей класса, причем это не контролируется (в принципе)  smile Так что вариант от Lazin с wrapper лично мне нравится больше собственного (за что ему счас +1 поставлю  smile )

PM MAIL   Вверх
mes
Дата 9.9.2008, 15:14 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 144
Всего: 250



Цитата(xvr @  9.9.2008,  15:05 Найти цитируемый пост)
это требование размещать макрос TABLE_DEF после описания всех остальных полей класса, причем это не контролируется (в принципе) 

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

Добавлено через 1 минуту и 59 секунд
Цитата(xvr @  9.9.2008,  15:05 Найти цитируемый пост)
Так что вариант от Lazin с wrapper лично мне нравится больше собственного (за что ему счас +1 поставлю  smile )

ага .. вариант с wrapper определено самый функциональный, переносимый и самое главное  безопасный

Это сообщение отредактировал(а) mes - 9.9.2008, 15:14


--------------------
PM MAIL WWW   Вверх
Ответ в темуСоздание новой темы Создание опроса
Правила форума "С++:Общие вопросы"
Earnest Daevaorn

Добро пожаловать!

  • Черновик стандарта C++ (за октябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика(4.4мб).
  • Черновик стандарта C (за сентябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика (3.4мб).
  • Прежде чем задать вопрос, прочтите это и/или это!
  • Здесь хранится весь мировой запас ссылок на документы, связанные с C++ :)
  • Не брезгуйте пользоваться тегами [code=cpp][/code].
  • Пожалуйста, не просите написать за вас программы в этом разделе - для этого существует "Центр Помощи".
  • C++ FAQ

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Earnest Daevaorn

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.0588 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.