Can't access non-const member functions of objects in C ++ std :: set

Post is a class I made. I have a bunch of these in the main function that I pass to messageTimeOut (and some other functions). In messageTimeOut, using the itorator, I loop through them and access the various member functions. However, I can only access the const member functions of the message that the iterator points to. If I try to access non-member functions, I get the error:

"In function" void messageTimeOut (threadParameters *) ': main.cpp: 74: 33: error: Passing a "const" message as argument' this' "void Message :: setTimedOut (bool)" discards the [-fpermissive] qualifiers. "

It makes sense that I cannot access the non-const member function of the const message object, but how can I make it a non-context Message object so that I can access the non-member functions and modify the message? Thanks to

Part of my code:

     [ . . . ]

void messageTimeOut( threadParameters* params )
{
     set<Message>::iterator it = params->messages->begin();
     [ . . . ]
    for ( ; it != params->messages->end(); ++it )
    {
        if ( (it->createdTime() + RESPONSE_WAIT) < GetTickCount() ) 
        {
            it->setTimedOut(true); // error 
        }
    }
    ReleaseMutex(sentQueueMutex);
}

     [ . . . ]

int main()
{
    threadParameters rmparameters;
    set<Message> sentMessages;
     [ . . . ]


    rmparameters.logFile = &logFile;
    rmparameters.socket = socketDesciptor;
    rmparameters.messages = &sentMessages;
      [ . . . ]

    messageTimeOut( rmparameters );
      [ . . . ]

    return 0;
}

      

+2


source to share


3 answers


You can not.

The elements inside a std :: set are always constant, because otherwise the user could modify the order in the set by changing the element belonging to the set.



Note that it doesn't matter that the function you call does not change the order, as std :: set has no way of checking this.

The usual way to fix this is to remove the item from the set, change it, and then insert it again. Another way is to use a card, even if it will likely cause you to duplicate some data.

+9


source


You will not be able to modify the contents of std :: set. Here's a given test case:

#include <set>
#include <iostream>

void print(int & data) {}

int main() {
    std::set<int> objects;

    objects.insert(3);
    print(*objects.find(3));
}

      

Clang will report the following errors:



blah.cc:14:2: error: no matching function for call to 'print'
        print(*objects.find(3));
        ^~~~~
blah.cc:4:6: note: candidate function not viable: 1st argument ('const int') would lose const qualifier
void print(int & data) {
     ^

      

Hence, it looks like using a set is not the right solution for this.

+1


source


The objects in the collection are constants, which means they are not mutable. Here are some options

1) Create copies of the messages in a new set
2) Remove the messages, mutate them, and put them back.
3) Remove the "timeout" field from the message.

      

Of these, I prefer number 3. The fact that you are trying to mutate messages is "bad code smell". If you avoided all data changes and instead created a new structure (like std :: map), you could reduce the amount of thread synchronization.

0


source







All Articles