0

I have been google all over the place and am unable to find a working example for how to use std::set and control the insert order. I found comments for my type of structure but I get a compile error.

I am trying to sort on myMaskName so I get

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

vs. this default order

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

This is my test code:

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();
}

This is the error I see on compile. It doesn't like me accessing the members.

./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());

All the examples I have founder are for int or std::string. I have found no example of someone using a class like this beyond saying setup a compare struct and use that.

So what am I doing wrong?

This is the corrected code for pointers:

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();
}

Changing the return to const fix the compile problem for pointer declaration using the struct way (see corrected code above) but I also tried to do it using an inline vs. struct:

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

After removing the FoIxCompareMaskNewComp from the “std::set maskList” declaration line I got this compile error.

error: ‘bool operator<(const FoIxCompareMaskNew*, const FoIxCompareMaskNew*)’ must have an argument of class or enumerated type inline bool operator< (const FoIxCompareMaskNew * p_lhs, const FoIxCompareMaskNew * p_rhs)

If I don’t do it with pointers then the inline below works, were inline is:

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

std::set<FoIxCompareMaskNew> maskList

So why doesn’t it work if I declare it as a pointer but does if it not?

user3416126
  • 148
  • 11
  • 1
    `std::string MaskName() {return myMaskName;}` should be `std::string MaskName() const {return myMaskName;}` That is, add the keyword `const` as indicated. – Ben Voigt Dec 21 '17 at 21:37
  • Sometimes you need to ask for help with your overall goal (as you did here), but sometimes you already have everything right except one tiny detail and need to look really closely (and ask for help on) the error message itself. – Ben Voigt Dec 21 '17 at 21:40
  • Changing the return to const fix the compile problem for pointer declaration using the struct way but I also tried to use the – user3416126 Dec 22 '17 at 14:48
  • Using an `operator<` definition instead of a struct does not work, because the language has already defined what `<` means for pointers. – Ben Voigt Dec 22 '17 at 15:49

0 Answers0