Why does the C++ map type argument require an empty constructor when using []?

Solution 1:

This issue comes with operator[]. Quote from SGI documentation:

data_type& operator[](const key_type& k) - Returns a reference to the object that is associated with a particular key. If the map does not already contain such an object, operator[] inserts the default object data_type().

If you don't have default constructor you can use insert/find functions. Following example works fine:

myMap.insert( std::map< int, MyClass >::value_type ( 1, MyClass(1) ) );
myMap.find( 1 )->second;

Solution 2:

Yes. Values in STL containers need to maintain copy semantics. IOW, they need to behave like primitive types (e.g. int) which means, among other things, they should be default-constructible.

Without this (and others requirements) it would be needlessly hard to implement the various internal copy/move/swap/compare operations on the data structures with which STL containers are implemented.

Upon reference to the C++ Standard, I see my answer was not accurate. Default-construction is, in fact, not a requirement:

From 20.1.4.1:

The default constructor is not required. Certain container class member function signatures specify the default constructor as a default argument. T() must be a well-defined expression ...

So, strictly speaking, your value type only needs to be default constructible if you happen to be using a function of the container that uses the default constructor in its signature.

The real requirements (23.1.3) from all values stored in STL containers are CopyConstructible and Assignable.

There are also other specific requirements for particular containers as well, such as being Comparable (e.g. for keys in a map).


Incidentally, the following compiles with no error on comeau:

#include <map>

class MyClass
{
public:
    MyClass(int t);
};

int main()
{
    std::map<int, MyClass> myMap;
}

So this might be a g++ problem.

Solution 3:

Check requirements of stored type of the stl::map. Many stl collection require that stored type contains some specific properties (default constructor, copy constructor, etc.).

Constructor without arguments is needed by the stl::map, because it's used, when operator[] is invoked with the key, which hasn't already been kept by the map. In this case the operator[] inserts the new entry consisting of the new key and value constructed using parameterless constructor. And this new value is then returned.