0

I am working on compiling some old api code that was written back in mid to late 90's, it is written in C++98 and I am using GCC on linux.

I have this line of offending code:

UnpackCommunityData(data.insert(std::map<long, CommunityData>::value_type(ReadLong(), CommunityData())).first);

The above line leads to this error:

msg/Profile/SMsgProfileMsgs.cpp: In member function ‘virtual void WONMsg::SMsgProfile2DownloadCommunityTreeReply::Unpack()’:
msg/Profile/SMsgProfileMsgs.cpp:1410:107: error: cannot bind non-const lvalue reference of type ‘std::map<long int, WONMsg::CommunityData>::iterator&’ {aka ‘std::_Rb_tree_iterator<std::pair<const long int, WONMsg::CommunityData> >&’} to an rvalue of type ‘std::_Rb_tree_iterator<std::pair<const long int, WONMsg::CommunityData> >’
UnpackCommunityData(data.insert(std::map<long, CommunityData>::value_type(ReadLong(), CommunityData())).first);
                       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~

These are the definitions:

    struct CommunityData {
     long CommunitySeq;
     long TrustLevelId;
     std::wstring Name;
     std::wstring Descr;
     long JoinByInvitationOnly;
     long ParentCommunitySeq;
     std::vector<long> ChildrenSeq;
    };
    std::map<long, CommunityData>           data;
    void UnpackCommunityData(std::map<long, CommunityData>::iterator&);

void SMsgProfile2DownloadCommunityTreeReply::UnpackCommunityData(std::map<long, CommunityData>::iterator& itInfo) {
    itInfo->second.CommunitySeq = itInfo->first;
    itInfo->second.TrustLevelId = ReadLong();
    ReadWString(itInfo->second.Name);
    ReadWString(itInfo->second.Descr);
    itInfo->second.JoinByInvitationOnly = ReadLong();
    itInfo->second.ParentCommunitySeq = ReadLong();

    unsigned short n = ReadShort();
    for (int i = 0; i < n; ++i) itInfo->second.ChildrenSeq.push_back(ReadLong());

    databyname.insert(std::map<std::wstring, long>::value_type(itInfo->second.Name, itInfo->second.CommunitySeq));
}

I'm not well versed in templates in C++, so I do not have a clue as to how to fix this error.

I would like it if someone could walk me through the error and solution.

  • 1
    Nothing to do with templates `data.insert( ... )` returns a temporary value that will expire at the end of the line and the compiler is worried that by passing it into a function that takes the value as a reference you may attempt to keep a pointer or reference to that temporary object around past its death. – user4581301 Nov 22 '21 at 18:30
  • 1
    Make it take the iterator by value: `void UnpackCommunityData(std::map::iterator);` if you need to step the iterator. You can make it a `const&` if not - but an iterator is supposed to be cheap to copy so, by value should be fine. – Ted Lyngmo Nov 22 '21 at 18:31
  • 1
    If Ted's solution doesn't work for you, expand the question to explain why and give more details so we can offer up better options. – user4581301 Nov 22 '21 at 18:33
  • 1
    You are passing a temporary to a function that intends (or claims intent) to modify its parameter. Either the parameter should be a const reference, or the argument should not be a temporary. Modifying a temporary before it gets destroyed strongly implies that you are not doing what you think you are doing. – Drew Dormann Nov 22 '21 at 18:34
  • 1
    Thanks everyone, I understand now. – user3654535 Nov 22 '21 at 19:11
  • Seeing the update, Ted's solution should get you what you want. That said, you don't really make use of the iterator, you don't do any iterating. Your code might be a bit simpler if you dereference the iterator and pass a reference to the `pair` referenced by the iterator into the function. – user4581301 Nov 22 '21 at 20:10

0 Answers0