简体   繁体   English

函数作为模板参数问题

[英]Functions as template parameters issue

I have this problem bothering me. 我有这个问题困扰我。 I have the FSM class which associate keys to callbacks 我有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;
};

And some callbacks classes 还有一些回调类

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;
    }
};

Now if into the main I do: 现在,如果进入主要我做:

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

The first call is fine, in the second one compiler complains: 第一个调用很好,在第二个编译器抱怨:

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’

Also notice that the following is fine 另请注意以下情况

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

Any idea? 任何想法? Thanks in advance for your help. 在此先感谢您的帮助。

Simone 西蒙娜

You haven't defined Callback::operator(). 您尚未定义Callback :: operator()。 There is no secound function for Callback just the function from CallbackBase which takes a CallbackBase and a int as parameters! Callback没有Secound函数只是来自CallbackBase的函数,它将CallbackBase和int作为参数! This is why the compiler moans about "unresolved overloaded function type". 这就是编译器呻吟“未解决的重载函数类型”的原因。

The type of the inherited function is bool (CallbackBase::*operator())(int). 继承函数的类型是bool(CallbackBase :: * operator())(int)。 This function can be automatically converted to a bool (Callback::*operator())(int) because you can always apply a Callback to a function that accepts only a CallbackBase. 此函数可以自动转换为bool(Callback :: * operator())(int),因为您始终可以将Callback应用于仅接受CallbackBase的函数。 This is the reason why the following works - it's a automatic cast happening there. 这就是为什么以下工作的原因 - 它是在那里发生的自动演员。

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

The problem happens with the template type deduction: 模板类型扣除会出现问题:

template< typename Callback_t, bool (Callback_t::*CallbackFunct_t)(int) >
with: Callback_t = Callback, CallbackFunct_t = bool (CallbackBase::*CallbackFunct_t)(int)

This doesn't work since the types that given via Callback_t and the type required by the function pointer do not match when instanciating the callback function. 这不起作用,因为在实现回调函数时,通过Callback_t给出的类型和函数指针所需的类型不匹配。 You can resolve the problem with a explicit cast of the function pointer to (Callback::*operator())(int) before the type deduction takes place. 在类型推导发生之前,您可以通过显式转换函数指针(Callback :: * operator())(int)来解决问题。 If you change the callback function to the following you do not require the two types to be identical and it compiles without the cast. 如果将回调函数更改为以下内容,则不需要两种类型相同,并且在没有强制转换的情况下进行编译。

template< typename Callback_t>
bool callback( int x )
{
    return Callback_t()( x );
}

What I don't understand is why you add the virtual function. 我不明白的是你添加虚函数的原因。 Wouldn't the following do the same, be more simple and readable and even faster (no virtual function call)? 以下不会做同样的事情,更简单,更易读,甚至更快(没有虚函数调用)? The doCall function would be required to be public. doCall函数必须是公共的。

template< typename Callback_t>
bool callback( int x )
{
    return Callback_t().doCall( x );
}

Another improvement would be to make the callback function static. 另一个改进是使回调函数保持静态。 It would be even more simple if the doCall functions would be static - this would make the callback function obsolete and would avoid creating a temporary to call doCall. 如果doCall函数是静态的,那将更加简单 - 这将使回调函数过时并避免创建临时调用doCall。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM