Статический массив константных указателей на перегруженную, шаблонизированную функцию-член - PullRequest
1 голос
/ 15 сентября 2009

Инициализация статического массива ... с указателями констант ... на перегруженные, шаблонизированные функции-члены. Есть ли способ сделать это (стандартный код C ++ 03)? Я имею в виду, если у меня есть шаблон класса


template <class T1, class U1, typename R1>
class Some_class {
public:
    typedef T1 T;
    typedef U1 U;
    typedef R1 R;

    R operator()(T& v) { /* dereference pointer to a derived class (U),
                            overloaded member function (U::f) */ };

private:
    static R (U::* const pmfi[/* # of overloaded functions in U */])(T&);
};

Used as

template <class BASE, typename RET>
class Other_class : public Some_class<BASE, Other_class<BASE, RET>, RET> {
    RET f(/* type derived from BASE */) {}
    RET f(/* other type derived from BASE */) {}
    RET f(/* another type derived from BASE */) {}
    ...
};

Question: how can I initialize de array pmfi (no typedefs, please)?

Примечания:
1. Поскольку статический массив ДОЛЖЕН быть инициализирован в области видимости файла, параметры шаблона и pmfi должны быть полностью квалифицированными (единственный известный мне способ получить доступ к параметрам шаблона вне области видимости класса - это определить их ...).
2. Пока все хорошо. Никаких проблем с компилятором (Comeau 4.3.10.1). Проблемы начинают появляться, когда я пытаюсь заполнить список инициализаторов {...}.
2.1. Компилятор жалуется, что список аргументов шаблона отсутствует, независимо от того, что я делаю.
2.2. Я понятия не имею, как выбрать правильную перегруженную функцию U :: f.

Кстати, это своего рода генератор таблицы переходов из списка boost.preprocessor. Код, который я пытаюсь реализовать, конечно, намного сложнее, чем этот, но в этом его суть.

Спасибо за любую помощь

1 Ответ

1 голос
/ 15 сентября 2009

Чтобы использовать BOOST_PP_ENUM в указанном вами способе, вам понадобится макрос, который принимает «число» и дает выражение, являющееся адресом соответствующего члена соответствующего класса. Я не вижу хорошего способа сделать это без явного списка, если все нужные функции не имеют именованных имен (например, memfun1, memfun2 и т. Д.). За исключением случая, будет проще явно перечислить выражения адреса функции, которые использовались для BOOST_PP_ENUM.

Вы используете идентификаторы в этом массиве, которые совпадают с параметрами шаблона в Some_class.

R (U::* const pmfi[])(T&) = { /* ... */ }

Это действительно должен быть шаблонный член Some_class?

template< class T, class U, class R >
R (U::* const Some_class<T, U, R>::pmfi[])(T&) = { /* ... */ }

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

Редактировать, опубликовать редактирование: Если я вас правильно понял, вы не сможете сделать то, что предложили, потому что массив указателей должен иметь точно правильную подпись.

Сокращая это до простого примера указателя на функцию, вы не можете сделать это:

void f(Derived&);

void (*p)(Base&) = &f;

в противном случае это подорвет безопасность типов:

OtherDerived od; // derived from Base, but no from Derived

 // I've managed to pass something that isn't a Derived reference to f
 // without an explicit (and dangerous) cast
(*p)(od);

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...