Код (Text): class mutex_type_a { public: class scoped_lock { .... }; .... }; class mutex_type_b { public: class scoped_lock { .... }; .... }; #define acquire_type_a(mut) mutex_type_a owner_##mut(mut); #define acquire_type_b(mut) mutex_type_b owner_##mut(mut); Где-то в коде: void dummy::foo() { acquire_type_a(mutex); boo(); } Хочется сделать так, чтобы макрос acquire был всего один, и имел только один параметр - мутекс. И чтобы scoped_lock у него нужный создавался. Вижу пока что только один вариант: scoped_lock - внешний класс, у которого шаблонный конструктор, выводящий тип мутекса. Внутри конструктора пихаем реализацию в boost::any. Код (Text): template <class T> class scoped_lock_impl // Он делает lock/unlock { public: scoped_lock_impl(T& mut); ~scoped_lock_impl(); }; class scoped_lock { public: template <class T> scoped_lock(T& mut) { impl = scoped_lock_impl<T>(mut); } private: boost::any impl; }; И тогда: #define acquire(mut) scoped_lock owner_##mut(mut); Главное что мне тут не нравится - это динамический полиморфизм с выделением места в куче. 99% что компилятор не сможет заоптимизить это в простые вызовы lock/unlock.
maxdiver Ага, вроде бы даже работает. Только я не понимаю, как))) Разве это можно сделать не отходя от стандарта?
_DEN_ В смысле? Там через шаблоны и их специализации всё реализовано, для стандартных и stl-ных типов уже всё специализовано, для своих приходится самому делать через BOOST_REGISTER_TYPE. Так что никакой магии вроде ) На старых ms-ных компиляторах там вроде есть какая-то магия, что BOOST_TYPEOF безо всяких специализаций работает, но это уже благодаря несоответствию стандарту
maxdiver Ну понятное дело что не через указатели и юнионы. Но как, как именно это сделано? Чтобы получить тип по значению, нужно сделать вывод типа. Вывод типа умеют делать только шаблонные функции. Единственный способ снаружи вынуть какую-то информацию о типе, который вывела функция - это sizeof. sizeof(foo(obj)). Этого явно недостаточно - разные типы могут иметь одинаковый размер. boost мне позволил сделать следующее без регистрации: Код (Text): struct foo { struct boo {}; }; foo f; BOOST_TYPEOF(f)::boo b;
_DEN_ Компилятор какой? VC <= 7.0? Тогда как раз я про него и говорил, там используются какие-то баги компилера, и за счёт этого typeof обходится без регистрации. А вообще, если без этого, т.е. на всех остальных компилерах, то не так уж и изящно этот typeof выглядит - для каждого своего типа по REGISTER'у писать.
А там и было на sizeof основано. [спустя полчаса борьбы с компилером ) ] Вот такая значит [] получилась Вроде даже работает Каждому типу ставим уникальный айди по номеру строки (тут конечно слабое место, айди бы как-нибудь получше желательно определять), этот айди берём в качестве параметра шаблона, и этот же айди выдирается из перегружаемой функции как sizeof от возвращаемого ей массива.
9-ка. Там не баги, там экстеншен __sizeof. Все это очень хорошо, вот только __LINE__ это тоже экстеншен. Судя по всему, эту хрень на на действующем стандарте сделать действительно невозможно. Я вижу только один вариант, это макросы такого вида: REGISTER1(my_type1); REGISTER2(my_type2); REGISTER3(my_type3); REGISTER4(my_type4); REGISTER5(my_type5); Избавиться от индексов (а следовательно - сделать возможным разнесение по хедерам без зависимости порядка включения), в рамках стандарта видимо не получится.
Как это __LINE__ экстеншн? Что же она в стандарте тогда делает? Другое дело, что номер строки - не лучший способ для id. В качестве основы нужно что-нибудь типа макроса COUNTER из буста ))