Я видел и ваш пример, и ответ на другой вопрос. Но если вы говорите о члене m_dispatcher, ситуация будет совсем другой.
Что касается исходного вопроса, то нет способа перебрать методы класса. Вы можете удалить повторение только в add ("method", T :: method) с помощью макроса:
#define ADD(methodname) add(#methodname, T::methodname)
где '#' превратит имя метода в строку, как требуется (разверните макрос по мере необходимости). В случае методов с аналогичными именами это устраняет источник потенциальных опечаток, следовательно, это ИМХО очень желательно.
Единственный способ перечислить имена методов IMHO - это синтаксический анализ вывода «nm» (в Linux или даже в Windows через порты binutils) для таких файлов (вы можете попросить его разобрать символы C ++). Если вы хотите поддержать это, вы можете захотеть, чтобы initDispatcher был определен в отдельном исходном файле для автоматической генерации. Нет лучшего способа, чем этот, и да, он может быть безобразным или идеальным в зависимости от ваших ограничений. Кстати, это также позволяет проверить, что авторы не перегружают методы. Однако я не знаю, можно ли фильтровать публичные методы.
Я отвечаю о строке в конструкторе A и B. Я думаю, что проблему можно решить с помощью любопытно повторяющегося шаблона, примененного к Dispatchable:
template <typename T>
class Dispatchable
{
public:
virtual ~Dispatchable() {}
//! Dispatch the call
void dispatch( const char *methodName )
{
dispatcher()->dispatch( this, methodName );
}
protected:
static Dispatcher<T> dispatcher() {
return Dispatcher<T>::singleton();
//Or otherwise, for extra optimization, using a suggestion from:
//http://www.parashift.com/c++-faq-lite/ctors.html#faq-10.12
static Dispatcher<T>& disp = Dispatcher<T>::singleton();
return disp;
}
};
Отказ от ответственности: я не смог протестировать-скомпилировать это (у меня нет компилятора). Возможно, вам придется объявить Dispatcher в прямом направлении, но поскольку он получает аргумент шаблона, я думаю, что поиск в зависимости от аргументов делает это ненужным (мне не хватает гуру C ++, чтобы быть уверенным в этом).
Я добавил для удобства метод dispatcher (), если он нужен где-то еще (в противном случае вы можете встроить его в dispatch ()).
Причина, по которой CRTP здесь так прост и так сложен в другом потоке, в том, что здесь ваш член не был статичным. Сначала я подумал о том, чтобы сделать его статическим, затем я подумал, что нет причин сохранять результат вызова singleton () и тратить память, а затем я искал его и нашел это решение. Я сомневаюсь, если дополнительная ссылка в dispatcher () действительно сэкономит дополнительное время.
В любом случае, если нужен член m_dispatcher, его можно инициализировать в конструкторе Dispatchable ().
О вашем примере, поскольку initDispatcher () - это шаблонный метод, я искренне сомневаюсь, что необходимо прочитать метод method1 и method2. A::initDispatcher(Dispatcher<B> dispatcher)
правильно добавит B :: method1 к диспетчеру.