2010-04-21 75 views
1
#include <list> 
#include <set> 
#include <iterator> 
#include <algorithm> 

using namespace std; 

class MyContainer { 
public: 
string value; 

    MyContainer& operator=(const string& s) { 
     this->value = s; 
     return *this; 
    } 
}; 

int main() 
{ 
    list<string> strings; 
    strings.push_back("0"); 
    strings.push_back("1"); 
    strings.push_back("2"); 

    set<MyContainer> containers; 
    copy(strings.begin(), strings.end(), inserter(containers, containers.end())); 
} 

前面的代碼不能編譯。在標準的C++方式下,錯誤輸出是冗長而難以理解的。關鍵部分似乎是這樣...有關插入迭代器和重載運算符的C++ STL問題

/usr/include/c++/4.4/bits/stl_algobase.h:313: error: no match for ‘operator=’ in ‘__result.std::insert_iterator::operator* [with _Container = std::set, std::allocator >]() = __first.std::_List_iterator::operator* [with _Tp = std::basic_string, std::allocator >]()’

......這意味着賦值運算符所需的定義沒有定義。我查看了insert_iterator的源代碼,並指出它已經重載了賦值運算符。複製算法必須使用插入迭代器重載的賦值運算符來完成它的工作(?)。

我想這是因爲我的輸入迭代器位於字符串的容器上,而我的輸出迭代器位於MyContainers的容器上,重載的insert_iterator賦值運算符無法再工作。

這是我最好的猜測,但我可能是錯的。

那麼,爲什麼這不起作用,我該如何實現我想要做的?

回答

4

什麼工作會使用構造函數(這會更有意義,而不是分配):

class MyContainer { 
public: 
string value; 

    MyContainer(const string& s): value(s) { 
    } 
}; 

然後第二個問題是,該集還要求其內容具有可比性。

至於原因,通過重載operator=insert_iterator作品:

insert_iterator<Container>& operator= (typename Container::const_reference value); 

正如你可以看到,右邊的值必須是容器的值類型或隱式轉換到它,這正是一個(非顯式)構造函數實現並且賦值運算符不能。


從技術上講,你也可以讓它在不改變類通過提供合適的轉換函數的工作(例如:如果你不想要一個不明確的構造函數):

MyContainer from_string(const std::string& s) 
{ 
    MyContainer m; 
    m = s; //or any other method how to turn a string into MyContainer 
    return m; 
} 

可以使用與std::transform

transform(strings.begin(), strings.end(), inserter(containers, containers.end()), from_string); 
+0

謝謝!!!!!!! – rshepherd 2010-04-21 19:21:17

+0

'std :: set'需要'operator <()' – wilhelmtell 2010-04-21 20:29:51

+0

嚴格地說,它不是。這是一個小問題,並在答案中簡要提及。 – UncleBens 2010-04-21 20:55:05

3

您需要添加:
1.需要字符串的構造函數(您正試圖將字符串添加到可以包含MyContainer對象的容器中)。
2.布爾運算符<(組使用它在默認情況下,以比較元素)
例如:

class MyContainer 
{ 
    public: 
    MyContainer(const string& v):value(v){}; 
}; 
bool operator <(const MyContainer &c1, const MyContainer &c2) 
{ 
return c1.value <c2.value; 
} 
1

的問題是雙重的:

  1. 您正試圖從string對象的列表中填充一組MyContainer對象
  2. ...從string對象列表中。

copy()算法嘗試將每個string對象轉換爲MyContainer對象。在C++中,從string類型添加到類MyContainer轉換支持輸入MyContainer你需要添加一個構造函數string類型的參數:

struct MyContainer { 
    MyContainer(const string& s) : value(s) { } 
    bool operator<(const MyContainer& o) const { return value < o.value; } 

private: 
    string s; 
}; 

你並不需要一個賦值運算符,因爲編譯器可以得到複製構造函數完成複製:將string轉換爲MyContainer,然後使用默認賦值運算符將一個MyContainer對象分配到另一個上。但是,您將需要operator<(),因爲C++集已排序。