2013-07-21 33 views
0

我想學習如何使用用戶定義的類使用bind2nd,但我發現了一個錯誤,我想不通,儘管我的尋找到其他的努力如何解決資源以獲得援助。Bind2nd問題與用戶定義的類

幫助將不勝感激,謝謝。

的main.cpp

#include <algorithm> 
#include <vector> 

class F 
{ 
public: 
    int operator()(int a, int b) 
    { 
    return a * b; 
    } 
}; 

int main(void) 
{ 
    std::vector<int> bases; 

    for(int i = 0; i < 5; ++i) 
    bases.push_back(i); 

    std::transform(bases.begin(), bases.end(), bases.begin(), std::bind2nd(F(), 2)); 
    // Error C2664: '_OutIt std::transform<std::_Vector_iterator<_Myvec>,std::_Vector_iterator<_Myvec>, 
    // std::binder2nd<_Fn2>>(_InIt,_InIt,_OutIt,_Fn1)' : cannot convert parameter 4 from 
    // 'std::binder2nd<_Fn2>' to 'std::binder2nd<_Fn2>' 
} 
+0

注意,'的std :: bind2nd'已被棄用在C++ 11更通用的和靈活的解決方案。 – juanchopanza

回答

2

首先你已經包括功能使用粘合劑功能。

其次你需要指定你的operator()爲const。

第三,爲了要獲得類型的特徵信息,如* first_argument_type *等,它是最好的,你的情況,從的std :: binary_function繼承。

#include <algorithm> 
#include <vector> 
#include <functional> 
#include <iterator> 
#include <iostream> 

struct F : public std::binary_function<int, int, int> 
{ 
    int operator()(int a, int b) const 
    { 
     return a * b; 
    } 
}; 

int main(void) 
{ 
    std::vector<int> bases; 

    for(int i = 0; i < 5; ++i) 
     bases.push_back(i); 

    std::transform(bases.begin(), bases.end(), bases.begin(), std::bind2nd(F(), 2)); 

    // print it to stdout 
    std::copy(bases.begin(), bases.end(), std::ostream_iterator<int>(std::cout, " ")); 
    std::cout << std::endl; 
} 

編輯

,如果你已經獲得了C++ 11意識到編譯器和STDLIB,你的載體填充的代碼可以很容易地改寫爲:

std::vector<int> bases(5); 
int i = 0; 

std::generate(bases.begin(), bases.end(), [&i]() { return ++i; }); 

用C + +11有一個新的聯編程序(從boost :: bind中移出)std :: bind。如果你願意,這樣可以更加靈活,你可以嘗試一下。如:

using namespace std::placeholders; 
std::transform(std::begin(bases), std::end(bases), std::begin(bases), 
       std::bind(F(), 2, _1)); 

(我剛剛所看到的,從下面的答案,那a.lasram提到的新的std ::綁定,我不知道你是否允許你的項目,或什麼的,使用新的C++ 11,而不是舊的C++ 03功能。如果我是你,如果你不被允許的話,我會的(引用着名的Alexandrescu先生的話)「打電話給你的代理人。」: ))

Btw。瑞安(見註釋)是絕對正確的,當他提到,即使我最複雜的std ::生成的東西;)可以用更短的書面iota

std::iota(bases.begin(), bases.end(), 1); 

的std ::絲毫被數字定義。所以你也必須包含它。

希望有所幫助。

+0

謝謝,完美無缺! –

+0

@Leif乾杯先生!謝謝你接受它...請參閱我的更新以獲取更多信息。你甚至可以把你的std.begin()換成基於範圍的開始和結束...... – Stefan

+0

實際上,通過調用['std :: iota'](http://en.cppreference),可以更簡化矢量填充代碼。 com/w/cpp/algorithm/iota),如'std :: iota(std :: begin(bases),std :: end(bases),0)'。 – 2013-07-21 20:59:21

2

這就完成了Stefan的回答,他指出std::bind將const引用作爲函子參數,因此operator()必須是const。

現在,您的二元仿函數必須適應std::bind2ndbind2nd預計F到的typedef first_argument_typesecond_argument_typeresult_type

class F 
{ 
public: 
    typedef int first_argument_type; 
    typedef int second_argument_type; 
    typedef int result_type; 

    int operator()(int a, int b) const 
    { 
     return a * b; 
    } 
}; 

C++ 11引入std::bind不具有這些所需的typedef