2

I'm working on an MFC application using VS 2012. In this application, I want to sanitize a container of CString objects by using the Trim() member function. First, I used a std::vector as container, as shown in the following MCVE:

#define _AFXDLL    // CString
#include <afx.h>   // CString
#include <vector>

int main()
{
    std::vector<CString> v;
    v.push_back(_T("Test"));
    v.begin()->Trim();
    return 0;
}

This compiles and works as expected. Then, I wanted to replace the std::vector by a std::set. Therefore, I included #include <set> instead of #include <vector> and changed main() as follows:

int main()
{
    std::set<CString> s;
    s.insert(_T("Test"));
    s.begin()->Trim();
    return 0;
}

However, this gives me the following compile error on the s.begin()->Trim(); line:

error C2663: 'ATL::CStringT>>::Trim' : 3 overloads have no legal conversion for 'this' pointer

The documentation of the error basically says:

[...] This error can be caused by invoking a non-const member function on a const object. [...]

However, compared to the vector version, I didn't add any const qualifier. Also, std::set::begin() provides a non-const iterator, just as std::vector::begin() does. I found similar questions on error C2663, for example, this one. But in most of these cases, someone tried to modify a member from a const function, which is not the case in my code.

Why can't I use Trim() on CString objects in a std::set and how can I fix this problem?

honk
  • 9,137
  • 11
  • 75
  • 83
  • 1
    Possible duplicate of [How to update an existing element of std::set?](https://stackoverflow.com/questions/7340434/how-to-update-an-existing-element-of-stdset) – François Andrieux Jul 20 '17 at 15:04
  • 1
    Values inside a `std::set` are `const`, because they are also the key defining the order within the set. – BoBTFish Jul 20 '17 at 15:04
  • They need to be, `std::set` (and `std::map` alike) organises its data internally in a binary search tree, typically a red/black tree. If you modified the entries (keys only for maps), you'd break sort order and any guarantees coming with... – Aconcagua Jul 20 '17 at 15:08
  • 2
    The elements in a `set` are `const`, because altering them could change their relative ordering and thus break the set internal data structure (typically some sort of balanced tree), as it could alter the ordering relation between the various elements - which is definitely a possibility with what you want to do. – Matteo Italia Jul 20 '17 at 15:14
  • Thank you all! It's quite obvious after reading your comments. I really should have been able to figure this out by myself. I guess I'm getting old... – honk Jul 20 '17 at 15:24

1 Answers1

2

How can I trim strings stored in a std::set?

You can't and you shouldn't. Elements in a std::set are ordered internally. If you were allowed to change them in place, that would break the ordering.

Your best option is to remove the existing item from the set and add the modified item to the set.

R Sahu
  • 204,454
  • 14
  • 159
  • 270