Вы не определили Callback :: operator (). Для Callback нет функции secound, только функция из CallbackBase, которая принимает CallbackBase и int в качестве параметров! Вот почему компилятор стонет о «неразрешенном типе перегруженной функции».
Тип унаследованной функции - bool (CallbackBase :: * operator ()) (int). Эта функция может быть автоматически преобразована в bool (Callback :: * operator ()) (int), потому что вы всегда можете применить Callback к функции, которая принимает только CallbackBase. Это причина того, что следующие работы - это автоматическое приведение там.
typedef bool (Callback::*Function_t)( int );
Function_t aFunction = &Callback::operator();
Проблема возникает с удержанием типа шаблона:
template< typename Callback_t, bool (Callback_t::*CallbackFunct_t)(int) >
with: Callback_t = Callback, CallbackFunct_t = bool (CallbackBase::*CallbackFunct_t)(int)
Это не работает, поскольку типы, которые передаются через Callback_t, и тип, требуемый указателем функции, не совпадают при создании экземпляра функции обратного вызова.
Вы можете решить проблему с помощью явного приведения указателя на функцию (Callback :: * operator ()) (int) до того, как произойдет вывод типа.
Если вы измените функцию обратного вызова на следующую, вам не нужно, чтобы два типа были идентичными, и она компилируется без преобразования.
template< typename Callback_t>
bool callback( int x )
{
return Callback_t()( x );
}
Чего я не понимаю, так это почему вы добавляете виртуальную функцию. Разве следующее не сделает то же самое, будет более простым, читаемым и даже более быстрым (без вызова виртуальной функции)? Функция doCall должна быть общедоступной.
template< typename Callback_t>
bool callback( int x )
{
return Callback_t().doCall( x );
}
Еще одним улучшением было бы сделать функцию обратного вызова статической. Было бы еще проще, если бы функции doCall были статическими - это сделало бы функцию обратного вызова устаревшей и позволило бы избежать создания временного элемента для вызова doCall.