คำถาม C++ STL ที่เกี่ยวข้องกับตัววนซ้ำและตัวดำเนินการโอเวอร์โหลด

#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++ มาตรฐาน ผลลัพธ์ข้อผิดพลาดจะเป็นแบบละเอียดและเข้าใจยาก ส่วนสำคัญน่าจะเป็นเรื่องนี้...

/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 ที่โอเวอร์โหลดไม่สามารถทำงานได้อีกต่อไป

นี่เป็นการเดาที่ดีที่สุดของฉัน แต่ฉันอาจผิด

เหตุใดจึงไม่ได้ผลและฉันจะบรรลุสิ่งที่ฉันพยายามทำได้อย่างไร


person rshepherd    schedule 21.04.2010    source แหล่งที่มา


คำตอบ (3)


สิ่งที่จะใช้ได้คือการใช้คอนสตรัคเตอร์ (ซึ่งจะสมเหตุสมผลมากกว่าแทนที่จะมอบหมายงาน):

class MyContainer {
public:
 string value;

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

ปัญหาที่สองคือเซตนั้นยังต้องการให้เนื้อหาเปรียบเทียบกันด้วย

สำหรับสาเหตุ insert_iterator ทำงานโดยการโอเวอร์โหลด operator=:

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

อย่างที่คุณเห็น ค่าทางขวามือจะต้องเป็นประเภทค่าของคอนเทนเนอร์หรือสามารถแปลงเป็นค่านั้นได้โดยปริยาย ซึ่งเป็นสิ่งที่ Constructor (ไม่ชัดเจน) บรรลุผลสำเร็จและผู้ดำเนินการกำหนดไม่ได้


ในทางเทคนิคแล้ว คุณสามารถทำให้มันใช้งานได้โดยไม่ต้องเปลี่ยนคลาส (เช่น หากคุณไม่ต้องการตัวสร้างที่ไม่ชัดเจน) โดยจัดให้มีฟังก์ชันการแปลงที่เหมาะสม:

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);
person UncleBens    schedule 21.04.2010
comment
std::set ความต้องการ operator<() - person wilhelmtell; 22.04.2010
comment
พูดอย่างเคร่งครัดมันไม่ได้ มันเป็นปัญหาข้างเคียงที่นี่ และกล่าวถึงสั้น ๆ ในคำตอบ - person UncleBens; 22.04.2010

คุณต้องเพิ่ม:
1. ตัวสร้างที่รับสตริง (คุณกำลังพยายามเพิ่มสตริงลงในคอนเทนเนอร์ที่สามารถมีวัตถุ MyContainer)
2. ตัวดำเนินการ bool ‹ (set ใช้เป็นค่าเริ่มต้นเพื่อเปรียบเทียบองค์ประกอบ)
ตัวอย่างเช่น :

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

ปัญหาคือสองเท่า:

  1. คุณกำลังพยายามเติมชุดของวัตถุ MyContainer
  2. ... จากรายการวัตถุ string

อัลกอริทึม copy() พยายามแปลงแต่ละวัตถุ string เป็นวัตถุ MyContainer ใน C++ เพื่อเพิ่มการสนับสนุนการแปลงคลาส MyContainer จากประเภท string เป็นประเภท 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++ ถูกจัดเรียงแล้ว

person wilhelmtell    schedule 21.04.2010