Обратиться к nested-типу через объект?

Тема в разделе "LANGS.C", создана пользователем _DEN_, 15 янв 2009.

  1. _DEN_

    _DEN_ DEN

    Публикаций:
    0
    Регистрация:
    8 окт 2003
    Сообщения:
    5.383
    Адрес:
    Йобастан
    Код (Text):
    1. class mutex_type_a
    2. {
    3. public:
    4.  
    5.     class scoped_lock
    6.     {
    7.         ....
    8.     };
    9.  
    10.     ....
    11. };
    12.  
    13. class mutex_type_b
    14. {
    15. public:
    16.  
    17.     class scoped_lock
    18.     {
    19.         ....
    20.     };
    21.  
    22.     ....
    23. };
    24.  
    25. #define acquire_type_a(mut) mutex_type_a owner_##mut(mut);
    26. #define acquire_type_b(mut) mutex_type_b owner_##mut(mut);
    27.  
    28. Где-то в коде:
    29.  
    30. void dummy::foo()
    31. {
    32.     acquire_type_a(mutex);
    33.     boo();
    34. }
    Хочется сделать так, чтобы макрос acquire был всего один, и имел только один параметр - мутекс. И чтобы scoped_lock у него нужный создавался.

    Вижу пока что только один вариант: scoped_lock - внешний класс, у которого шаблонный конструктор, выводящий тип мутекса. Внутри конструктора пихаем реализацию в boost::any.

    Код (Text):
    1. template <class T>
    2. class scoped_lock_impl // Он делает lock/unlock
    3. {
    4. public:
    5.     scoped_lock_impl(T& mut);
    6.     ~scoped_lock_impl();
    7. };
    8.  
    9. class scoped_lock
    10. {
    11. public:
    12.  
    13.     template <class T>
    14.     scoped_lock(T& mut)
    15.     {
    16.         impl = scoped_lock_impl<T>(mut);
    17.     }
    18.  
    19. private:
    20.  
    21.     boost::any impl;
    22. };
    23.  
    24. И тогда:
    25.  
    26. #define acquire(mut) scoped_lock owner_##mut(mut);
    Главное что мне тут не нравится - это динамический полиморфизм с выделением места в куче. 99% что компилятор не сможет заоптимизить это в простые вызовы lock/unlock.
     
  2. maxdiver

    maxdiver Max

    Публикаций:
    0
    Регистрация:
    18 июл 2006
    Сообщения:
    308
    Адрес:
    Саратов
    BOOST_TYPEOF?
     
  3. _DEN_

    _DEN_ DEN

    Публикаций:
    0
    Регистрация:
    8 окт 2003
    Сообщения:
    5.383
    Адрес:
    Йобастан
    maxdiver

    Ага, вроде бы даже работает. Только я не понимаю, как))) Разве это можно сделать не отходя от стандарта?
     
  4. maxdiver

    maxdiver Max

    Публикаций:
    0
    Регистрация:
    18 июл 2006
    Сообщения:
    308
    Адрес:
    Саратов
    _DEN_
    В смысле? :)
    Там через шаблоны и их специализации всё реализовано, для стандартных и stl-ных типов уже всё специализовано, для своих приходится самому делать через BOOST_REGISTER_TYPE. Так что никакой магии вроде )
    На старых ms-ных компиляторах там вроде есть какая-то магия, что BOOST_TYPEOF безо всяких специализаций работает, но это уже благодаря несоответствию стандарту :)
     
  5. _DEN_

    _DEN_ DEN

    Публикаций:
    0
    Регистрация:
    8 окт 2003
    Сообщения:
    5.383
    Адрес:
    Йобастан
    maxdiver

    Ну понятное дело что не через указатели и юнионы. Но как, как именно это сделано? Чтобы получить тип по значению, нужно сделать вывод типа. Вывод типа умеют делать только шаблонные функции. Единственный способ снаружи вынуть какую-то информацию о типе, который вывела функция - это sizeof. sizeof(foo(obj)). Этого явно недостаточно - разные типы могут иметь одинаковый размер.


    boost мне позволил сделать следующее без регистрации:

    Код (Text):
    1. struct foo
    2. {
    3.     struct boo {};
    4. };
    5.  
    6. foo f;
    7.  
    8. BOOST_TYPEOF(f)::boo b;
     
  6. maxdiver

    maxdiver Max

    Публикаций:
    0
    Регистрация:
    18 июл 2006
    Сообщения:
    308
    Адрес:
    Саратов
    _DEN_
    Компилятор какой? VC <= 7.0? Тогда как раз я про него и говорил, там используются какие-то баги компилера, и за счёт этого typeof обходится без регистрации.

    А вообще, если без этого, т.е. на всех остальных компилерах, то не так уж и изящно этот typeof выглядит - для каждого своего типа по REGISTER'у писать.
     
  7. maxdiver

    maxdiver Max

    Публикаций:
    0
    Регистрация:
    18 июл 2006
    Сообщения:
    308
    Адрес:
    Саратов
    А там и было на sizeof основано.

    [спустя полчаса борьбы с компилером :)) ]
    Вот такая значит [] получилась :lol:
    Вроде даже работает :)
    Каждому типу ставим уникальный айди по номеру строки (тут конечно слабое место, айди бы как-нибудь получше желательно определять), этот айди берём в качестве параметра шаблона, и этот же айди выдирается из перегружаемой функции как sizeof от возвращаемого ей массива.
     
  8. _DEN_

    _DEN_ DEN

    Публикаций:
    0
    Регистрация:
    8 окт 2003
    Сообщения:
    5.383
    Адрес:
    Йобастан
    9-ка. Там не баги, там экстеншен __sizeof.


    Все это очень хорошо, вот только __LINE__ это тоже экстеншен. Судя по всему, эту хрень на на действующем стандарте сделать действительно невозможно.

    Я вижу только один вариант, это макросы такого вида:

    REGISTER1(my_type1);
    REGISTER2(my_type2);
    REGISTER3(my_type3);
    REGISTER4(my_type4);
    REGISTER5(my_type5);

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

    maxdiver Max

    Публикаций:
    0
    Регистрация:
    18 июл 2006
    Сообщения:
    308
    Адрес:
    Саратов
    Как это __LINE__ экстеншн? Что же она в стандарте тогда делает? :)
    Другое дело, что номер строки - не лучший способ для id.
    В качестве основы нужно что-нибудь типа макроса COUNTER из буста :)))