2015-08-31 46 views
1

,我有以下簽名的方法:從boost :: bind_t自動轉換,以提高::功能

template<typename T> 
void 
register_msg_action(const pmt::pmt_t& name, 
     boost::function<T(pmt::pmt_t)> converter, 
     boost::function<void(T)> action) 

pmt_t是一個完整的類型,你問之前)

以及超載取T converter(pmt::pmt_t)void converter(T)(即原始C/C++函數),以及上述boost::function<>和C風格函數參數的所有排列。這給我留下了4種不同的方法。

我想避免增加更多的方法。不過,我會做最普通的事情就是調用像

register_msg_action(pmt::mp("key"), 
    pmt::to_long, /* "raw" function long(pmt_t) */ 
    boost::bind(&my_class::void_method_of_long, this, _1) /* CAVEAT */ 
); 

我的做法是,/* CAVEAT */參數是隱式轉換爲boost::function<void(T)>,但然而,這似乎並沒有這樣的情況(G ++ 5.1。 1):

error: no matching function for call to ‘register_msg_action(pmt::pmt_t, boost::function<long int(boost::intrusive_ptr<pmt::pmt_base>)>&, boost::_bi::bind_t<void, void (*)(long int), boost::_bi::list1<boost::arg<1> > >)’ 
    register_msg_action(pmt::mp("hi"), long_function, boost::bind(&my_class::void_method_of_long, this ,_1)); 

...所有其他候選人(boost :: function,boost :: function); (T(pmt_t),升壓::功能); (T(pmt_t),無效(T))...

test.cc:56:1: note: candidate: template<class T> void register_msg_action(const pmt_t&, T (*)(pmt::pmt_t), boost::function<void(T)>) 
register_msg_action(const pmt::pmt_t& name, 
^ 
test.cc:56:1: note: template argument deduction/substitution failed: 
test.cc:80:76: note: ‘boost::_bi::bind_t<void, void (*)(long int), boost::_bi::list1<boost::arg<1> > >’ is not derived from ‘boost::function<void(T)>’ 
    register_msg_action(pmt::mp("key"), pmt::to_long, boost::bind(&my_class::void_method_of_long, this, _1)); 

現在,做

boost::function<void(long)> action (boost::bind(&my_class::void_method_of_long, this, _1)); 
register_msg_action(pmt::mp("key"), pmt::to_long, action); 

精美的作品。因爲甚至有一個構造函數,在boost::function需要boost::_bi::bind_t,我不知道我必須做什麼,使這項工作,沒有

  • 重新實現boost::function
  • 依靠C++ 11或更高版本(不能做使用boost:phoenix函數式編程(,傳統的編譯器支持)
  • 會嘗試這樣做,但我們必須支持增強版本並不都具有phoenix呢。

我擔心將第三個參數的類型添加爲額外的模板類型名稱,因爲這會破壞爲保證action(converter(pmt::pmt_t))工作而必需的參數列表類型安全性,並且說實話,我寧願處理更多的代碼,而不是檢查用戶的稍後模板化的g ++錯誤。

回答

3

問題是當T出現在boost::function的模板參數register_msg_action的簽名中。然後,如果您沒有用實際的boost::function對象調用它,則無法推斷。如果指定模板參數明確它應該工作:

register_msg_action<long>(pmt::mp("key"), 
    pmt::to_long, /* "raw" function long(pmt_t) */ 
    boost::bind(&my_class::void_method_of_long, this, _1) 
); 

如果你想繼續使用至少一個純函數的參數時,推導T的選項,你可以選擇明確使T非抵扣在其boost::function使用:

template <class T> 
struct NonDeduced 
{ 
    typedef T type; 
}; 

// T has to be specified explicitly at call site 
template<typename T> 
void 
register_msg_action(const pmt::pmt_t& name, 
     boost::function<typename NonDeduced<T>::type (pmt::pmt_t)> converter, 
     boost::function<void(typename NonDeduced<T>::type)> action) 

// T deducible from converter 
template<typename T> 
void 
register_msg_action(const pmt::pmt_t& name, 
     T converter(pmt::pmt_t), 
     boost::function<void(typename NonDeduced<T>::type)> action) 

// T deducible from action 
template<typename T> 
void 
register_msg_action(const pmt::pmt_t& name, 
     boost::function<typename NonDeduced<T>::type (pmt::pmt_t)> converter, 
     void action(T)) 

// T deducible from both, must match 
template<typename T> 
void 
register_msg_action(const pmt::pmt_t& name, 
     T converter(pmt::pmt_t), 
     void action(T)) 

[Live example]

+0

這樣做,真的!我會重新修改我的語法,使其成爲一項功能,而不是給用戶帶來額外的負擔。 –

+0

順便說一下,強制我的用戶指定模板參數會將我的方法編號減少到1,這是一種改進,我猜。我認爲最好是強迫用戶明確地做某件事情,而不是讓他有機會做某些事情,甚至可以讓有經驗的人花幾分鐘的時間來弄清楚編譯器在抱怨什麼。 –