亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

當涉及std:function或lambda函數時,C+11不推斷類型

當涉及std:function或lambda函數時,C+11不推斷類型

C++
慕森卡 2019-08-04 10:00:44
當涉及std:function或lambda函數時,C+11不推斷類型當我定義這個函數時,template<class A>set<A> test(const set<A>& input) {     return input;}我可以用test(mySet)在代碼的其他地方,無需顯式定義模板類型。但是,當我使用以下函數時:template<class A>set<A> filter(const set<A>& input,function<bool(A)> compare) {     set<A> ret;     for(auto it = input.begin(); it != input.end(); it++) {         if(compare(*it)) {             ret.insert(*it);         }     }     return ret;}當我調用此函數時,使用filter(mySet,[](int i) { return i%2==0; });我得到以下錯誤:錯誤:沒有調用‘filter’的匹配函數(std:set&,main():)然而,所有這些版本做工作:std::function<bool(int)> func = [](int i) { return i%2 ==0; };set<int> myNewSet = filter(mySet,func); set<int> myNewSet = filter<int>(mySet,[](int i) { return i%2==0; }); set<int> myNewSet = filter(mySet,function<bool(int)>([](int i){return i%2==0;}));當我將lambda函數直接放入表達式而不直接創建std::function?編輯:根據注釋中Luc Danton的建議,這里有一個替代函數,它不需要顯式傳遞模板。template<class A,class CompareFunction>set<A> filter(const set<A>& input,CompareFunction compare) {     set<A> ret;     for(auto it = input.begin(); it != input.end(); it++) {         if(compare(*it)) {             ret.insert(*it);         }     }     return ret;}這可以被set<int> result = filter(myIntSet,[](int i) { i % 2 == 0; });而不需要模板。編譯器甚至可以在某種程度上猜測返回類型,使用新的Dectype關鍵字和使用新函數返回類型語法。下面是一個示例,它使用一個過濾函數和一個基于值生成鍵的函數將集合轉換為映射:template<class Value,class CompareType,class IndexType>auto filter(const set<Value>& input,CompareType compare,IndexType index) ->  map<decltype(index(*(input.begin()))),Value> {     map<decltype(index(*(input.begin()))),Value> ret;     for(auto it = input.begin(); it != input.end(); it++) {         if(compare(*it)) {             ret[index(*it)] = *it;         }     }     return ret;}也可以在不直接使用模板的情況下調用它,如map<string,int> s = filter(myIntSet,[](int i) { return i%2==0; },[](int i) { return toString(i); });
查看完整描述

3 回答

?
縹緲止盈

TA貢獻2041條經驗 獲得超4個贊

別管你的案子了。因為這太復雜了,無法進行分析。

以這個簡單的例子為例:

 template<typename T>
 struct X 
 {
     X(T data) {}
 };

 template<typename T>
 void f(X<T> x) {}

現在打電話f作為:

 f(10);

在這里你可能會想T將被推斷為int 和因此,上述函數調用應該可以工作。但事實并非如此。為了保持簡單,想象一下另一個構造函數int作為:

 template<typename T>
 struct X 
 {
     X(T data) {}
     X(int data) {} //another constructor
 };

現在呢T當我寫的時候f(10)?井,T任何類型。

請注意,可能還有許多其他這樣的情況。以這種專業化為例:

 template<typename T>
 struct X<T*>         //specialized for pointers
 {
    X(int data) {}; 
 };

現在呢T應推斷為呼叫f(10)?現在似乎更難了。

因此,它是不可還原的上下文,這解釋了為什么您的代碼不能工作。std::function這是一個相同的情況-只是表面看上去很復雜。請注意蘭巴斯非類型std::function-它們基本上是編譯器生成類的實例(即它們是編譯器生成的類的函子異類類型比std::function).




查看完整回答
反對 回復 2019-08-05
?
aluckdog

TA貢獻1847條經驗 獲得超7個贊

如果我們有:

template <typename R, typename T>int myfunc(std::function<R(T)> lambda){
  return lambda(2);}int r = myfunc([](int i) { return i + 1; });

它不會編譯。但如果你之前聲明:

template <typename Func, typename Arg1>static auto getFuncType(Func* func = nullptr, Arg1* arg1 = nullptr) -> decltype((*func)(*arg1));
template <typename Func>int myfunc(Func lambda){
  return myfunc<int, decltype(getFuncType<Func, int>())>(lambda);}

您可以使用lambda參數毫無問題地調用函數。

這里有兩個新代碼。

首先,我們有一個函數聲明,它僅適用于根據給定的模板參數返回一個舊的函數指針類型:

template <typename Func, typename Arg1>static auto getFuncType(Func* func = nullptr, Arg1* arg1 = nullptr) -> decltype((*func)(*arg1)) {};

其次,我們有一個函數,它接受一個模板參數來構建我們期望的lambda類型,調用‘getFuncType’:

template <typename Func>int myfunc(Func lambda){
  return myfunc<int, decltype(getFuncType<Func, int>())>(lambda);}

有了正確的模板參數,現在我們可以調用真正的‘myfunc’。完整的代碼是:

template <typename R, typename T>int myfunc(std::function<R(T)> lambda){
  return lambda(2);}template <typename Func, typename Arg1>static auto getFuncType(Func* func = nullptr, Arg1* arg1 = nullptr) -> 
  decltype((*func)(*arg1)) {};template <typename Func>int myfunc(Func lambda){
  return myfunc<int, decltype(getFuncType<Func, int>())>(lambda);}int r = myfunc([](int i) { return i + 1; });

您可以為“getFuncType”聲明與lambda參數匹配的任何重載。例如:

template <typename Func, typename Arg1, typename Arg2>static auto getFuncType(Func* func = nullptr, Arg1* arg1 = nullptr, Arg2*
 arg2 = nullptr) -> decltype((*func)(*arg1, *arg2)) {};





查看完整回答
反對 回復 2019-08-05
  • 3 回答
  • 0 關注
  • 600 瀏覽

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號