2015-05-31 37 views
0

我正在學習如何在C++中使用標準泛型算法。在下面的代碼示例中,我試圖通過將兩個操作(string to const char* and const char* to double)合併爲一個的自定義撰寫函數的幫助將字符串轉換爲double。在C++中使用適應性函數對象編譯錯誤

我寫了unary_composer作爲一個適應性功能對象。

然而,當我編譯它,我收到以下錯誤

錯誤2錯誤C2664:「雙unary_composer ::運算符()(常量 的std :: basic_string的< _Elem,_Traits,_AX> *) 「:不能從轉換參數1 '的std :: basic_string的< _Elem,_Traits,_AX>' 到 '常量 的std :: basic_string的< _Elem,_Traits,_AX> *

'

using namespace std; 

template<typename F1, typename F2> 
class unary_composer : public unary_function<typename F2::argument_type, typename F1::result_type> 
{ 
    F1 f1; 
    F2 f2; 

public: 
unary_composer(F1 lf1, F2 lf2) : f1(lf1), f2(lf2){} 

typename F1::result_type operator()(typename F2::argument_type x) 
{ 
    return f1(f2(x)); 
} 

}; 

template <typename F1, typename F2> 
unary_composer<F1, F2> compose(F1 fone, F2 ftwo) 
{ 
    return unary_composer<F1, F2>(fone, ftwo); 
} 

int _tmain(int argc, _TCHAR* argv[]) 
{ 
    const int SZ = 9; 
    vector<string> vs(SZ); 

    srand(time(0)); 

    generate(vs.begin(), vs.end(), NumGenerator()); // Generates strings with random digits ex: "12.35". NumGenerator is defined in another source file. 

    vector<double> vd; 

    // Transform the strings to doubles 
    transform(vs.begin(), vs.end(), back_inserter(vd), compose(ptr_fun(atof), mem_fn(&string::c_str))); 

    copy(vd.begin(), vd.end(), ostream_iterator<double>(cout, " ")); // print to console 
    cout<<endl; 

    return 0; 
} 

當我使用mem_fun_ref代替mem_fn時,它工作正常。也許,錯誤說opeartor函數期望const string*類型的參數,但字符串正在通過。但我不知道如何解決它。我錯過了什麼?

PS:這個例子是從C++ VOL2(CHAPT 6)的思考採取

+0

感謝πάνταῥεῖ進行編輯。 – cexplorer

+0

問題是'mem_fn :: argument_type',它是一個指針。你堅持使用C++ 03還是可以使用更新的版本? – juanchopanza

+0

我正在使用VS2010。 – cexplorer

回答

1

std::mem_fnargument_type是指針類型,它打破您unary_composer它使用它作爲其own argument_type

取決於在你的編譯器C++ 11的支持程度,你可以在作曲改變的東西沿着

template<typename F1, typename F2> 
class unary_composer 
{ 
    F1 f1; 
    F2 f2; 

public: 
    unary_composer(F1 lf1, F2 lf2) : f1(lf1), f2(lf2){} 

    template <typename ARG> 
    auto operator()(ARG x)->decltype(f1(f2(x)) 
    { 
     return f1(f2(x)); 
    } 
}; 

行並調用它像這樣:

transform(vs.begin(), vs.end(), back_inserter(vd), 
      compose(std::atof, mem_fn(&string::c_str))); 

見一個working example

爲了完整起見,這裏不需要你推出任何函子版本:

transform(vs.begin(), vs.end(), back_inserter(vd), 
     [](const std::string& s) 
     {return std::stod(s);}); 

注意mem_funmem_fun_refunary_functor和其他人,因爲C++ 11棄用,將最有可能被刪除在C++ 17中。

+0

非常感謝。我正在嘗試通過decltype的文檔,但我仍然無法理解在此示例中如何推導Arg的類型。我想這裏使用decltype的目的是從f1(f2(x))推導出返回類型,但不清楚Arg的類型是如何被推導的。你能幫我嗎 ? – cexplorer

+1

@cexplorer你對'decltype'說得對。 'operator()'的技巧是它也是一個模板,它的模板參數'ARG'可以從傳遞給它的參數類型中推導出來。 – juanchopanza

+0

我明白了。代碼現在非常簡單!謝謝 – cexplorer