std::set с помощью указателей классов. Как управлять вставкой

Я везде гуглил и не смог найти рабочий пример того, как использовать std::set и управлять порядком вставки. Я нашел комментарии для своего типа структуры, но получаю ошибку компиляции.

Я пытаюсь отсортировать по myMaskName, поэтому получаю

  address  class
0x19ec220 TEST1 2 26
0x19eba90 TEST2 100 26
0x19ebb00 TEST3 230 26
0x19eba20 TEST4 240 26

по сравнению с этим порядком по умолчанию

0x19eba20 TEST4 240 26
0x19eba90 TEST2 100 26
0x19ebb00 TEST3 230 26
0x19ec220 TEST1 2 26

Это мой тестовый код:

class FoIxCompareMaskNew
{
public:
        // Main constructor.
        FoIxCompareMaskNew (const char *maskName,  const int&  startAddress, const int& numWords) :
                myMaskName(maskName),
                myStartAddress(startAddress),
                myNumberWords(numWords)
        {
        }

    ~FoIxCompareMaskNew ();

    std::string MaskName() {return myMaskName;}
    int StartAddress() {return myStartAddress;}
    int NumberWords() {return myNumberWords;}

private:

    std::string myMaskName;
    int     myStartAddress;
    int     myNumberWords;
};

struct FoIxCompareMaskNewComp {
    bool operator()(const FoIxCompareMaskNew* p_lhs, const FoIxCompareMaskNew* p_rhs) const
    {
        std::string temp = p_lhs->MaskName();
        return temp.compare(p_rhs->MaskName());
    }
};

void newWay()
{
    std::multiset<FoIxCompareMaskNew *, FoIxCompareMaskNewComp> maskList;
    std::multiset<FoIxCompareMaskNew *, FoIxCompareMaskNewComp> maskList2;
    FoIxCompareMaskNew * list[4];

    list[0] = new FoIxCompareMaskNew("TEST1", 2, 26);
    list[2] = new FoIxCompareMaskNew("TEST3", 230, 26);
    list[1] = new FoIxCompareMaskNew("TEST2", 100, 26);
    list[3] = new FoIxCompareMaskNew("TEST4", 240, 26);

maskList.insert(list[0] );
    maskList.insert(list[1] );
    maskList2.insert(list[0] );
    maskList2.insert(list[1] );
    maskList2.insert(list[2] );
    maskList2.insert(list[3] );
}

int main(int, char**)
{
    newWay();
}

Это ошибка, которую я вижу при компиляции. Мне не нравится доступ к членам.

./main.C: In member function ‘bool FoIxCompareMaskNewComp::operator()(const FoIxCompareMaskNew*, const FoIxCompareMaskNew*) const’:
./main.C:205:38: error: passing ‘const FoIxCompareMaskNew’ as ‘this’ argument of ‘std::string FoIxCompareMaskNew::MaskName()’ discards qualifiers [-fpermissive]
   std::string temp = p_lhs->MaskName();
                                      ^
./main.C:206:39: error: passing ‘const FoIxCompareMaskNew’ as ‘this’ argument of ‘std::string FoIxCompareMaskNew::MaskName()’ discards qualifiers [-fpermissive]
   return temp.compare(p_rhs->MaskName());

Все примеры, которые у меня есть основателя, предназначены для int или std::string. Я не нашел ни одного примера, чтобы кто-то использовал такой класс, кроме того, что я сказал настроить структуру сравнения и использовать ее.

Так что я делаю неправильно?

Это исправленный код для указателей:

class FoIxCompareMaskNew
{
public:
        // Main constructor.
        FoIxCompareMaskNew (const char *maskName,  const int&  startAddress, const int& numWords) :
                myMaskName(maskName),
                myStartAddress(startAddress),
                myNumberWords(numWords)
        {
        }

    ~FoIxCompareMaskNew ();

    std::string MaskName() const {return myMaskName;}
    int StartAddress() const {return myStartAddress;}
    int NumberWords() const {return myNumberWords;}

private:

    std::string myMaskName;
    int     myStartAddress;
    int     myNumberWords;
};

struct FoIxCompareMaskNewComp {

    bool operator()(const FoIxCompareMaskNew* p_lhs, const FoIxCompareMaskNew* p_rhs) const
    {
        return (p_lhs->MaskName().compare(p_rhs->MaskName()) < 0);
    }
};

void newWay()
{
    std::multiset<FoIxCompareMaskNew *, FoIxCompareMaskNewComp> maskList;
    std::multiset<FoIxCompareMaskNew *, FoIxCompareMaskNewComp> maskList2;
    FoIxCompareMaskNew * list[4];

    list[0] = new FoIxCompareMaskNew("TEST1", 2, 26);
    list[2] = new FoIxCompareMaskNew("TEST3", 230, 26);
    list[1] = new FoIxCompareMaskNew("TEST2", 100, 26);
    list[3] = new FoIxCompareMaskNew("TEST4", 240, 26);

    for (int i = 0; i < 4; i++)
    {
        std::cout << "list[" << i << "] " << list[i] << std::endl;
    }

    maskList.insert(list[0] );
    maskList.insert(list[1] );
    maskList2.insert(list[0] );
    maskList2.insert(list[1] );
    maskList2.insert(list[2] );
    maskList2.insert(list[3] );

    for (auto it=maskList2.begin(); it!=maskList2.end(); ++it)
    {
        // Check first to see if the item in in the list and if so delete it.
        maskList.erase(*it);
        maskList.insert(*it);   // now insert the unique pointer
    }

    std::cout << std::endl << "Unique set of masks using erase check" << std::endl;
    for (auto it=maskList.begin(); it!=maskList.end(); ++it)
    {
        FoIxCompareMaskNew * node = (FoIxCompareMaskNew *)(*it);

        std::cout << node << " " << node->MaskName() << " " << node->StartAddress() << " " << node->NumberWords() << std::endl;
    }
    std::cout << std::endl;
}
int main(int, char**)
{
    std::cout << std::endl << "unique std::set list of pointers" << std::endl;
    newWay2();
}

Изменение возврата на const устраняет проблему компиляции для объявления указателя с использованием структуры (см. исправленный код выше), но я также пытался сделать это с помощью встроенной структуры и структуры:

inline bool operator< (const FoIxCompareMaskNew* p_lhs, const FoIxCompareMaskNew* p_rhs)
{
    return (p_lhs->MaskName().compare(p_rhs->MaskName()) < 0);
}

После удаления FoIxCompareMaskNewComp из строки объявления «std::set maskList» я получил эту ошибку компиляции.

ошибка: «логический оператор‹(const FoIxCompareMaskNew*, const FoIxCompareMaskNew*)» должен иметь аргумент класса или перечисляемого типа, встроенный логический оператор‹ (const FoIxCompareMaskNew * p_lhs, const FoIxCompareMaskNew * p_rhs)

Если я не делаю это с указателями, то встроенный ниже работает, где встроенный:

inline bool operator< (const FoIxCompareMaskNew lhs, const FoIxCompareMaskNew rhs)
{
    return (lhs.MaskName().compare(rhs.MaskName()) < 0);
}

std::set<FoIxCompareMaskNew> maskList

Так почему же это не работает, если я объявлю его указателем, но работает, если нет?


person user3416126    schedule 21.12.2017    source источник
comment
std::string MaskName() {return myMaskName;} должно быть std::string MaskName() const {return myMaskName;} То есть добавьте ключевое слово const как указано.   -  person Ben Voigt    schedule 22.12.2017
comment
Иногда вам нужно обратиться за помощью к вашей общей цели (как вы сделали здесь), но иногда у вас уже все есть правильно, за исключением одной крошечной детали, и вам нужно очень внимательно изучить (и попросить помощи) само сообщение об ошибке.   -  person Ben Voigt    schedule 22.12.2017
comment
Изменение возврата на const устраняет проблему компиляции для объявления указателя с использованием структуры, но я также пытался использовать   -  person user3416126    schedule 22.12.2017
comment
Использование определения operator< вместо структуры не работает, потому что язык уже определил, что < означает для указателей.   -  person Ben Voigt    schedule 22.12.2017