c++ - 函数作为模板参数问题

标签 c++ templates

这个问题困扰着我。我有 FSM 类,它将键与回调相关联

class FSM
{
public:

typedef bool (FSM::*InCallback_t)( int );
typedef std::map< std::string, InCallback_t > Table;

// Since I would like to allow the user to register both functors and class member    functions
template< typename Callback_t, bool (Callback_t::*CallbackFunct_t)(int) >
bool callback( int x )
{
    return (Callback_t().*CallbackFunct_t)( x );
}

void addCallback( const std::string& iKey, InCallback_t iCallback )
{
    _table.insert( std::make_pair( iKey, iCallback ) );
}

    [ ... ]

private:
    Table _table;
};

还有一些回调类

class CallbackBase
{
public:

    bool operator()( int x ){ return doCall( x ); }

private:
    virtual bool doCall( int x ){ return true; }
};


class Callback: public CallbackBase
{
private:
    bool doCall( int x )
    {
        std::cout << "Callback\n";
        return true;
    }
};

现在如果进入主要我做的:

FSM aFSM;
// OK
aFSM.addCallback( "one", &FSM::callback< CallbackBase, &CallbackBase::operator() > );  
// KO
aFSM.addCallback( "two", &FSM::callback< Callback, &Callback::operator() > );

第一个调用没问题,第二个编译器报错:

Test.cpp: In function ‘int main(int, char**)’:
Test.cpp:104:77: error: no matching function for call to ‘FSM::addCallback(const char [4], <unresolved overloaded function type>)’
Test.cpp:104:77: note: candidate is:
Test.cpp:24:7: note: void FSM::addCallback(const string&, FSM::InCallback_t)
Test.cpp:24:7: note:   no known conversion for argument 2 from ‘<unresolved overloaded function type>’ to ‘FSM::InCallback_t’

另请注意,以下是可以的

typedef bool (Callback::*Function_t)( int );
Function_t aFunction = &Callback::operator();
(Callback().*aFunction)( 5 );

有什么想法吗? 预先感谢您的帮助。

西蒙

最佳答案

您还没有定义 Callback::operator()。 Callback 没有第二个函数,只是来自 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。

关于c++ - 函数作为模板参数问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7696260/

相关文章:

c++ - 基于条件的模板重载

C++链接器设计问题

c++ - 如何防止 GTK 按钮中的鼠标悬停效果

c++ - 在放大镜窗口上绘制(放大 API)

c++ - 将类型转换为唯一编号的模板元程序

c++ - 在 C++11 中,是否可以将模板函数包装在 std::function 中?

c++ - 封闭类的模板参数的默认参数

c++ - 使用 set 检测重复项

c++ - 基于类型的标签调度 : Is it possible to differently tag containers based on the tags of their elements?

templates - 如何使用模板返回节点集