簡體   English   中英

使用std :: tr1 :: function的成員回調函數出現“ No Match”錯誤

[英]'No Match' Errors with a member callback function using std::tr1::function

我正在嘗試使用指向公共成員函數的str :: tr1 :: function創建回調函數。

std::tr1::function < int (const string& , const MessageInfo* , const void* , const int , const void* ) > dssCallBack;
dssCallBack = &ABC::mDBtoDScallback;

該回調將傳遞給ABC類的另一個函數體內的函數。 ABC::mDBtoDScallback的簽名為

int DataserviceSubscriber::mDBtoDScallback(const string& strTopic, const MessageInfo* messageInfo, const void* data, const int dataLen, const void* callback_data)

當我嘗試編譯它時,我從g ++收到以下錯誤。

In file included from /usr/lib/gcc/x86_64-redhat-linux/4.4.6/../../../../include/c++/4.4.6/tr1/functional:56,
                 from ../src/bmrk/databus/ABC.hpp:17,
                 from ../src/bmrk/databus/ABC.cpp:1:
/usr/lib/gcc/x86_64-redhat-linux/4.4.6/../../../../include/c++/4.4.6/tr1_impl/functional: In static member function ‘static _Res std::tr1::_Function_handler<_Res(_ArgTypes ...), _Member _Class::*>::_M_invoke(const std::tr1::_Any_data&, _ArgTypes ...) [with _Class = ABC, _Member = int(const std::string&, const MessageInfo*, const void*, int, const void*), _Res = int, _ArgTypes = const std::string&, const MessageInfo*, const void*, int, const void*]’:
/usr/lib/gcc/x86_64-redhat-linux/4.4.6/../../../../include/c++/4.4.6/tr1_impl/functional:2005:   instantiated from ‘std::tr1::function<_Res(_ArgTypes ...)>::function(_Functor, typename __gnu_cxx::__enable_if<(! std::tr1::is_integral::value), std::tr1::function<_Res(_ArgTypes ...)>::_Useless>::__type) [with _Functor = int (ABC::*)(const std::string&, const MessageInfo*, const void*, int, const void*), _Res = int, _ArgTypes = const std::string&, const MessageInfo*, const void*, int, const void*]’

/usr/lib/gcc/x86_64-redhat-linux/4.4.6/../../../../include/c++/4.4.6/tr1_impl/functional:1885:   instantiated from ‘typename __gnu_cxx::__enable_if<(! std::tr1::is_integral::value), std::tr1::function<_Res(_ArgTypes ...)>&>::__type std::tr1::function<_Res(_ArgTypes ...)>::operator=(_Functor) [with _Functor = int (ABC::*)(const std::string&, const MessageInfo*, const void*, int, const void*), _Res = int, _ArgTypes = const std::string&, const MessageInfo*, const void*, int, const void*]’
../src/bmrk/databus/dataservice_subscriber.cpp:266:   instantiated from here

/usr/lib/gcc/x86_64-redhat-linux/4.4.6/../../../../include/c++/4.4.6/tr1_impl/functional:1714: error: no match for call to ‘(std::tr1::_Mem_fn<int (ABC::*)(const std::string&, const MessageInfo*, const void*, int, const void*)>) (const std::basic_string<char, std::char_traits<char>, std::allocator<char> >&, const MessageInfo*&, const void*&, int&, const void*&)’

/usr/lib/gcc/x86_64-redhat-linux/4.4.6/../../../../include/c++/4.4.6/tr1_impl/functional:546: note: candidates are: _Res std::tr1::_Mem_fn<_Res (_Class::*)(_ArgTypes ...)>::operator()(_Class&, _ArgTypes ...) const [with _Res = int, _Class = ABC, _ArgTypes = const std::string&, const MessageInfo*, const void*, int, const void*]

/usr/lib/gcc/x86_64-redhat-linux/4.4.6/../../../../include/c++/4.4.6/tr1_impl/functional:551: note:                 _Res std::tr1::_Mem_fn<_Res (_Class::*)(_ArgTypes ...)>::operator()(_Class*, _ArgTypes ...) const [with _Res = int, _Class = ABC, _ArgTypes = const std::string&, const MessageInfo*, const void*, int, const void*]

我試圖查看我在這里做錯了什么,但無法發現它。 我試圖查找,但找不到其他存在類似問題的人。 我可以使用C風格的typedef,但我想使用並保留C ++風格,在此過程中還習慣了C ++ 11中的一些較新內容。

謝謝。

編輯:根據邁克爾·伯爾(Michael Burr)的要求,正在從函數中調用回調,方法是參考此處的http://en.cppreference.com/w/cpp/utility/functional/function

int ABC::subs_rt(const vector<string> &symbols, raw_callback_t raw_callback, void *app_data, Error *error)
{
    DBtoDS_callback_data cbData;
    cbData.subscriber_callback = raw_callback;
    cbData.raw_callback_app_data = app_data;
    cbData.err = error;

    // Perform processing on 'symbols'
    // dss is a member of class ABC and has been initialized in constructor
    dss->AddSubscriptionPrefix(symbols);
    b_cancel_subscription = false;

    std::tr1::function < int (const string& , const MessageInfo* , const void* , const int , const void* ) > dssCallBack;
    dssCallBack = &DataserviceSubscriber::mDBtoDScallback;

    dss->Subscribe(dssCallBack, static_cast<const void*>(&cbData));

    return 0;
}

回調本身看起來像

int ABC::mDBtoDScallback(const string& strTopic, const MessageInfo* messageInfo, const void* data, const int dataLen, const void* callback_data)
{
    const DBtoDS_callback_data* cbData = static_cast<const DBtoDS_callback_data*>(callback_data);

    if(0 == messageInfo) // Version 1
    {
        // Do callback Stuff
    }
    else // Version 2
    {
        Subscriber::timeval_t now;
        TimeUtils::now(now);
        std::string payload(static_cast<const char*>(data), dataLen);

        // Do callback Stuff
    }
}

正如WhozCraig猜測的那樣,函數int ABC::mDBtoDScallback不是靜態的。 那是問題嗎? 我不能使此函數中使用的某些變量靜態化。 有什么解決辦法還是必須使用C樣式的函數指針?

謝謝。

編輯2:根據nm和WhozCraig的關注以及此鏈接, C ++:將函數分配給tr1 :: function對象

我將ABC :: subs_rt函數中的行更改為

std::tr1::function < int (const string& , const MessageInfo* , const void* , const int , const void* ) > dssCallBack;
//dssCallBack = std::tr1::bind(&ABC::mDBtoDScallback, this, std::tr1::placeholders::_1);
dssCallBack = std::tr1::bind(&ABC::mDBtoDScallback, this);

我嘗試了注釋和未注釋的選項,但是現在出現此錯誤

In file included from /usr/lib/gcc/x86_64-redhat-linux/4.4.6/../../../../include/c++/4.4.6/tr1/functional:56,
                 from ../src/bmrk/databus/ABC.hpp:17,
                 from ../src/bmrk/databus/ABC.cpp:1:
/usr/lib/gcc/x86_64-redhat-linux/4.4.6/../../../../include/c++/4.4.6/tr1_impl/functional: In member function ‘typename std::tr1::result_of<_Functor(typename std::tr1::result_of<std::tr1::_Mu<_Bound_args, std::tr1::is_bind_expression::value, (std::tr1::is_placeholder::value > 0)>(_Bound_args, std::tr1::tuple<_UElements ...>)>::type ...)>::type std::tr1::_Bind<_Functor(_Bound_args ...)>::__call(const std::tr1::tuple<_UElements ...>&, std::tr1::_Index_tuple<_Indexes ...>) [with _Args = const std::basic_string<char, std::char_traits<char>, std::allocator<char> >&, const MessageInfo*&, const void*&, int&, const void*&, int ..._Indexes = 0, _Functor = std::tr1::_Mem_fn<int (ABC::*)(const std::string&, const MessageInfo*, const void*, int, const void*)>, _Bound_args = ABC*]’:
/usr/lib/gcc/x86_64-redhat-linux/4.4.6/../../../../include/c++/4.4.6/tr1_impl/functional:1191:   instantiated from ‘typename std::tr1::result_of<_Functor(typename std::tr1::result_of<std::tr1::_Mu<_Bound_args, std::tr1::is_bind_expression::value, (std::tr1::is_placeholder::value > 0)>(_Bound_args, std::tr1::tuple<_UElements ...>)>::type ...)>::type std::tr1::_Bind<_Functor(_Bound_args ...)>::operator()(_Args& ...) [with _Args = const std::basic_string<char, std::char_traits<char>, std::allocator<char> >, const MessageInfo*, const void*, int, const void*, _Functor = std::tr1::_Mem_fn<int (ABC::*)(const std::string&, const MessageInfo*, const void*, int, const void*)>, _Bound_args = ABC*]’
/usr/lib/gcc/x86_64-redhat-linux/4.4.6/../../../../include/c++/4.4.6/tr1_impl/functional:1654:   instantiated from ‘static _Res std::tr1::_Function_handler<_Res(_ArgTypes ...), _Functor>::_M_invoke(const std::tr1::_Any_data&, _ArgTypes ...) [with _Res = int, _Functor = std::tr1::_Bind<std::tr1::_Mem_fn<int (ABC::*)(const std::string&, const MessageInfo*, const void*, int, const void*)>(ABC*)>, _ArgTypes = const std::string&, const MessageInfo*, const void*, int, const void*]’
/usr/lib/gcc/x86_64-redhat-linux/4.4.6/../../../../include/c++/4.4.6/tr1_impl/functional:2005:   instantiated from ‘std::tr1::function<_Res(_ArgTypes ...)>::function(_Functor, typename __gnu_cxx::__enable_if<(! std::tr1::is_integral::value), std::tr1::function<_Res(_ArgTypes ...)>::_Useless>::__type) [with _Functor = std::tr1::_Bind<std::tr1::_Mem_fn<int (ABC::*)(const std::string&, const MessageInfo*, const void*, int, const void*)>(ABC*)>, _Res = int, _ArgTypes = const std::string&, const MessageInfo*, const void*, int, const void*]’
/usr/lib/gcc/x86_64-redhat-linux/4.4.6/../../../../include/c++/4.4.6/tr1_impl/functional:1885:   instantiated from ‘typename __gnu_cxx::__enable_if<(! std::tr1::is_integral::value), std::tr1::function<_Res(_ArgTypes ...)>&>::__type std::tr1::function<_Res(_ArgTypes ...)>::operator=(_Functor) [with _Functor = std::tr1::_Bind<std::tr1::_Mem_fn<int (ABC::*)(const std::string&, const MessageInfo*, const void*, int, const void*)>(ABC*)>, _Res = int, _ArgTypes = const std::string&, const MessageInfo*, const void*, int, const void*]’
../src/bmrk/databus/ABC.cpp:266:   instantiated from here
/usr/lib/gcc/x86_64-redhat-linux/4.4.6/../../../../include/c++/4.4.6/tr1_impl/functional:1137: error: no match for call to ‘(std::tr1::_Mem_fn<int (ABC::*)(const std::string&, const MessageInfo*, const void*, int, const void*)>) (ABC*&)’
/usr/lib/gcc/x86_64-redhat-linux/4.4.6/../../../../include/c++/4.4.6/tr1_impl/functional:546: note: candidates are: _Res std::tr1::_Mem_fn<_Res (_Class::*)(_ArgTypes ...)>::operator()(_Class&, _ArgTypes ...) const [with _Res = int, _Class = ABC, _ArgTypes = const std::string&, const MessageInfo*, const void*, int, const void*]
/usr/lib/gcc/x86_64-redhat-linux/4.4.6/../../../../include/c++/4.4.6/tr1_impl/functional:551: note:                 _Res std::tr1::_Mem_fn<_Res (_Class::*)(_ArgTypes ...)>::operator()(_Class*, _ArgTypes ...) const [with _Res = int, _Class = ABC, _ArgTypes = const std::string&, const MessageInfo*, const void*, int, const void*]
make[1]: *** [ABC.lo] Error 1

問題的解決方案:鑒於我的要求,決定將我的回調設為靜態成員函數,並通過const void* callback_data傳遞指向父類對象的指針。 作為靜態函數,它可以訪問ABC類的私有函數並將參數傳遞給raw_callback 我從所有評論中獲得的幫助對我來說是一次很好的學習經歷,最終使我走向了解決方案。

static int ABC::mDBtoDScallback(const string& strTopic, const MessageInfo* messageInfo, const void* data, const int dataLen, const void* callback_data)
{
    const DBtoDS_callback_data* cbData = static_cast<const DBtoDS_callback_data*>(callback_data);

    TimeUtils::now(now);
    std::string payload(static_cast<const char*>(data), dataLen);

    string symbol;
    string sym;
    int pri_s = 0;

    if(0 == messageInfo)
    {
        parse_topic(strTopic, symbol, pri_s, cbData->err);
    }
    else
    {
        symbol = messageInfo->key();
        pri_s = ( messageInfo->has_pri_s() ? messageInfo->pri_s() : 0 );
    }
    if (cbData->subs->symbols_need_translation())
    {
        cbData->subs->translate_symbol(cbData->subs->_translator, symbol, sym, false);
    }
    else
    {
        sym = symbol;
    }

    cbData->subscriber_callback(cbData->subs, sym, pri_s, cbData->subs->prod, payload, now, cbData->raw_callback_app_data, cbData->err);
}

謝謝。

如果您知道要查找的位置,則源很簡單。 考慮以下代碼:

std::tr1::function < int (const string& , const MessageInfo* , const void* , const int , const void* ) > dssCallBack;
dssCallBack = &ABC::mDBtoDScallback;
dssCallBack(std::string(), nullptr, nullptr, 0, nullptr);

什么是this 您從未提供過。 因此, std::function不可能完成這項工作-您正在嘗試調用成員,但未提供對象。 什么是std::function應該做的,神奇地決定什么this應該是什么?

將兩種溶液是,綁定this使用std::bind ,或通過this作為參數,如在std::mem_fn

正如評論中所討論的,問題似乎是因為您的函數對象實際上是一個靜態的,非對象綁定的函數,而實際上卻是將其傳遞給成員。 據我所知,有幾種解決方法,您可能已經在考慮最簡單的解決方法。 使用靜態並將對象的指針作為參數傳遞。

另外,我不知道這是否適用於您的特定體系結構,但是以下內容很快就結合在一起,說明如何使用std::mem_fn<>std::function<> std::mem_fn<>使用指定對象調用成員std::function<> 這是一個獨立的示例,但我希望您能看到它對您有何幫助。

#include <iostream>
#include <functional>
using namespace std;

class MyClass
{
public:
    MyClass() {}

    int CallMe(void *p, int a, float f)
    {
        // use params herere
        cout << "CallMe fired : " << this << " !\n" << endl;
        return 0;
    }
};

int main()
{
    MyClass obj, obj2;
    std::function<int(MyClass*,void*,int,float)> fn(std::mem_fn(&MyClass::CallMe));

    cout << "Invoking CallMe with " << &obj << " object..." << endl;
    fn(&obj, NULL, 1, 2.0);

    cout << "Invoking CallMe with " << &obj2 << " object..." << endl;
    fn(&obj2, NULL, 1, 2.0);

    return 0;
}

輸出量

Invoking CallMe with 0x7fff5fbff7d8 object...
CallMe fired : 0x7fff5fbff7d8 !

Invoking CallMe with 0x7fff5fbff7d0 object...
CallMe fired : 0x7fff5fbff7d0 !

注意

cppreference.com上C ++ 11中提供的有關成員函數對象如何工作的內容吸引我。 並不是每個人都真正在乎這一點,我不知道他們是否正確地將其分配給虛擬機等,但我對此感到非常驚訝。

希望對您有所幫助,但是如果一位真正了解std :: function,std :: bind和std :: men_fn深度知識的std-lib專家之一,我已經准備好刪除它,以進行更簡潔的解釋(或將該片段撕成碎片)。 坦白地說,在通過std::function<>調用成員的SO上可能有更好的示例,但是我要說的將std::men_fn<>std::function<>一起使用的簡單性頗具吸引力。


虛擬派遣

在征求DeadMG的意見后,我真的很好奇虛擬調度是否有效。 我認為這是個很好的機會,因為我們提供了this指針,但沒有屏住呼吸,因為顯然我們將MyClass::CallMe成員的副地址傳遞給了std:::mem_fn<>的構造函數。

更新的源代碼以及由此產生的運行非常有趣。 注意兩個實例中使用的相同功能對象。 我不能說是否打算以這種方式工作(順便說一句),但這對我很有趣,盡管如此。

#include <iostream>
#include <functional>
using namespace std;

class MyClass
{
public:
    MyClass() {}

    virtual int CallMe(void *p, int a, float f)
    {
        // use params herere
        cout << "MyClass::CallMe fired : " << this << endl;
        return 0;
    }
};

class MyDerived : public MyClass
{
public:
    MyDerived() {}

    virtual int CallMe(void *p, int a, float f)
    {
        // use params herere
        cout << "MyDerived::CallMe fired : " << this << endl;
        return 0;
    }
};

int main()
{
    MyClass obj;
    MyDerived obj2;

    std::function<int(MyClass*,void*,int,float)> fn(std::mem_fn(&MyClass::CallMe));

    cout << "Invoking CallMe with " << &obj << " object..." << endl;
    fn(&obj, NULL, 1, 2.0);

    cout << "Invoking CallMe with " << &obj2 << " object..." << endl;
    fn(&obj2, NULL, 1, 2.0);

    return 0;
}

輸出量

Invoking CallMe with 000000000021FB58 object...
MyClass::CallMe fired : 000000000021FB58
Invoking CallMe with 000000000021FB78 object...
MyDerived::CallMe fired : 000000000021FB78

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM