Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Compile Errors - std::set with const members

Tags:

c++

I can't for the life of me figure out what's wrong with this code:

ClassA & doSomething (std::set<boost::shared_ptr<ClassB const> const > const & someSet)
{
  std::set<boost::shared_ptr<ClassB> > secondSet;
  for (std::set<boost::shared_ptr<ClassB const> const >::const_iterator it = someSet.begin(); it != someSet.end(); it++)
  {
    if (checkSomething(*it))
      secondSet.insert(boost::const_pointer_cast<ClassB>(*it));
  }
}

When I try to compile, I get the following errors at line 4 (the start of the for loop) from g++:

/usr/include/c++/4.4/ext/new_allocator.h:79: error: ‘const _Tp* __gnu_cxx::new_allocator<_Tp>::address(const _Tp&) const [with _Tp = const boost::shared_ptr<const ClassB>]’ cannot be overloaded
/usr/include/c++/4.4/ext/new_allocator.h:76: error: with ‘_Tp* __gnu_cxx::new_allocator<_Tp>::address(_Tp&) const [with _Tp = const boost::shared_ptr<const ClassB>]’

If I change the std::set declaration to contain non-const boost::shared_ptr the code compiles perfectly, but that mean I won't be able to enforce const-correctness in my code.

Has anyone got any idea as to what might be causing these errors? I've searched both Google & StackOverflow without any luck.

Here is a minimum (non-)working example:

#include <set>
#include <boost/shared_ptr.hpp>

class ClassB;

class ClassA
{
   public:
      ClassA & doSomething (std::set<boost::shared_ptr<ClassB const> const > const & someSet);
};

ClassA & doSomething (std::set<boost::shared_ptr<ClassB const> const > const & someSet)
{
   std::set<boost::shared_ptr<ClassB> > secondSet;
   for (std::set<boost::shared_ptr<ClassB const> const >::const_iterator it = someSet.begin(); it != someSet.end(); it++)
   {
      if (checkSomething(*it))
         secondSet.insert(boost::const_pointer_cast<ClassB>(*it));
   }

   return (*this);
}
like image 567
AVH Avatar asked Apr 02 '11 21:04

AVH


2 Answers

but that mean I won't be able to enforce const-correctness in my code

I think you may be wrong there. As long it is a smart pointer to a const object, you may only manipulate the pointers in the set, not the objects referred to. This is kind of the whole point, because a set cannot organize itself if it cannot touch the values.

It's the classical difference between

const char* x; // pointer to const char
const char* const x; // constant pointer to const char
char* const x; // constant pointer, to non-const char

Only this time with smartpointers. You can also verify for yourself that this simple test will fail for const items:

#include <set>

int main()
{
    std::set<const int> a;
    a.insert(1);
    return 1;
}

Once you remove 'const' it will work.


OT: If you want some container that has some kind of 'key' protection, you should perhaps look at map since in the value_type (std::pair) the key (.first) is always const - IIRC. I still think the point is moot with regard to const correctness of the container's elements.

like image 160
sehe Avatar answered Sep 30 '22 08:09

sehe


§23.1/3 states that std::set key types must be assignable and copy constructable; clearly a const type will not be assignable.

like image 37
ildjarn Avatar answered Sep 30 '22 07:09

ildjarn