Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why can't you put a const object into a STL container?

Tags:

c++

See the code below - I am trying to put a const object into a vector. I know the answer is "STL containers require objects to be assignable and copy constructable", but, without citing the standard, can anyone explain what the problem with doing this is? I don't understand why a class like this could not be copied (besides that c++ doesn't allow it).

All it is is a value stored that is not allowed to be changed - why can't putting it in a vector simply create another one of these objects?

#include <vector>

// Attempt 1
// /home/doriad/Test/Test.cxx:3:8: error: non-static const member ‘const int MyClass::x’, can’t use default assignment operator

// struct MyClass
// {
//   int const x;
//   MyClass(int x): x(x) {}
// };
// 
// int main()
// {
//   std::vector<MyClass> vec;
//   vec.push_back(MyClass(3));
//   return 0;
// }

// Attempt 2
// /home/doriad/Test/Test.cxx:28:23: error: assignment of read-only member ‘MyClass::x’
struct MyClass
{
  int const x;
  MyClass(int x): x(x) {}
  MyClass& operator= (const MyClass& other)
  {
    if (this != &other)
    {
      this->x = other.x;
    }

    return *this;
  }
};

int main()
{
  std::vector<MyClass> vec;
  vec.push_back(MyClass(3));
  return 0;
}

EDIT:

It is possible to do this with std::set and std::list. I guess it is the sort() function in std::vector that uses assignment. This is not UB right?

#include <set>

// Attempt 1
struct MyClass
{
  int const x;
  MyClass(int x): x(x) {}
  bool operator< (const MyClass &other) const;
};

bool MyClass::operator<(const MyClass &other) const
{
  if(this->x < other.x)
  {
    return true;
  }
  else if (other.x < this->x)
  {
    return false;
  }

}


int main()
{
  std::set<MyClass> container;
  container.insert(MyClass(3));
  return 0;
}
like image 419
David Doria Avatar asked Dec 31 '11 00:12

David Doria


Video Answer


1 Answers

EDIT2: (Removing a bunch of stuff that doesn't have to work) The C++11 standard states that the insert method for vector and deque (and the default implementation of push_back for that matter) requires the value type to be CopyAssignable, i.e., the value supports:

t= v;

Classes and structs with const members are not CopyAssignable by default, so what you want to do won't work.

This doc (n3173) has an explanation for the various container requirements.

like image 82
MSN Avatar answered Sep 25 '22 20:09

MSN