1

I remember that back in C++98, if you wanted to make an STL container of MyClass, you needed to provide default constructor to MyClass.

Was this specific to some implementations of STL? or was it mandated by the standard?

  • Q: Is this not necessary anymore?

Because it is not a good practice to provide default constructors when it makes no sense to have one...

Of course, I am not talking about the calls like

vector<MyClass> v(6);  

where you explicitly request that 6 default-initialized objects are to be created...

Christophe
  • 68,716
  • 7
  • 72
  • 138
Grim Fandango
  • 2,296
  • 1
  • 19
  • 27
  • 8
    There was no such requirement in C++98 to all containers. Which one of many containers do you mean? – 273K May 09 '22 at 07:29
  • 3
    It's always been the case that if you performed an operation that required default constructors then you need to provide them otherwise you didn't – Alan Birtles May 09 '22 at 07:33
  • The standard library is designed to follow the "don't pay for what you don't use" principle. That means the answer to your question depends on what you mean by "making an STL container of `MyClass`", and what STL container exactly you are trying to use. – Jakob Stark May 09 '22 at 07:41
  • 1
    @JakobStark, it is only a principle. Unfortunately, the committee don't always get it right -- see mutex in std::list (Stroustrup refers to it in one of his talks around 2010). Initially, some implementations of STL indeed required that MyClass had to be default constructible (Guy Davidson confirms it in "Beautiful C++ / chapter 2" ). I just did not know whether it was required by the standard, or it was just a gap in the standard. – Grim Fandango May 09 '22 at 09:34

1 Answers1

1

This quote is from the C++ Programming Language, Special edition , 2005 by Bjarne Stroustrup in section 16.3.4:

If a type does not have a default constructor, it is not possible to create a vector with elements of that type, without explicitly providing the value of each element.

So it was indeed a standard requirement. It was also required that (section 17.1.4) :

To be an element of a container, an object must be of a type that allows the container implementation to copy it. The container may copy it using a copy constructor or an assignment; in either case the result of the copy must be an equivalent object.

So yes, there were "official" constructor requirementsand the library implementation were supposed to be interchangeable and not add other requirements. (Already in the very first proposal for STL in 1995, the authors tried as much as possible to clearly indicate specifications and narrow down the implementation dependent flexibility.)

You therefore had to provide a default constructor in the case where you declared other constructors:

If a user has declared a default constructor, that one will be used; otherwise, the compiler will try to generate one if needed and if the user hasn't declared other constructors.

Nowadays, this requirement is relaxed. Since C++11:

The requirements that are imposed on the elements depend on the actual operations performed on the container.

So you can define a vector for a class without default constructor, if it doesn't make sense. This for example perfectly works (online demo):

class MyClass {
public: 
    MyClass(int x) {}
};
int main() {
    vector<MyClass> v; 
    MyClass test{1}; 
    v.push_back(test);
}

But it works only as long as you don't use any operation that would need the default constructor. For instance v.resize(6); would fail to compile.

Christophe
  • 68,716
  • 7
  • 72
  • 138
  • 1
    That's not what he is asking about. – Goswin von Brederlow May 09 '22 at 07:42
  • @GoswinvonBrederlow you were right. I misunderstood the initial question and edited. Thanks for the tip ;-) – Christophe May 09 '22 at 09:05
  • @Christophe, thank you for bringing up the history of this issue. – Grim Fandango May 09 '22 at 09:24
  • @GrimFandango thanks. I hope it helped. History can help to understand the present… and to reengineer legacy code. Who still remembers such awful things back in the early days of the language (first edition of The C++ programming langage book in 1986), when assignments and copy constructors were by default bitwise instead of member-wise? ;-) – Christophe May 09 '22 at 10:34
  • 1
    "If a type does not have a default constructor, it is not possible to create a vector with elements of that type, *without explicitly providing the value of each element.*" <- Does not seem like default constructors are mandatory. Old standard library implementations with old compilers were probably just buggy/nonconformant – Artyer May 09 '22 at 13:19
  • `If a type does not have a default constructor, it is not possible to create a vector with elements of that type, without explicitly providing the value of each element` that's still true today, you have to provide the value of every element for non-default constructible types it doesn't mean you can't/couldn't create a vector of a non-default constructible type – Alan Birtles May 10 '22 at 17:12