Why does C++ not have a const constructor?

Just because Image is const in your imaginary constructor doesn’t mean that what m_data points to is. You’d end up being able to assign a “pointer to const” to a “const pointer to non-const” inside your class, which would remove constness without a cast. This would obviously allow you to violate invariants and couldn’t be allowed.

As far as I know, any specific sets of const-ness that are needed can be accurately and completely specified within the current standard.

Another way to look at it is that const means the method doesn’t mutate your object’s state. A constructor’s sole purpose is to initialize an object’s state to be valid (well hopefully anyway – any constructors with side effects should be …carefully evaluated).

EDIT: In C++ constness applies to both members, and for pointers and references, to the accessible constness of the referred object. C++ consciously made the decision to split out these two different const-nesses. Firstly, do we agree that this code demonstrating the difference should compile and print out “non-const”?

#include <iostream>

struct Data
{
    void non_const() { std::cout << "non-const" << std::endl; }
};

struct Image
{
     Image(             Data & data ) : m_data( data ) {}

     void check() const { m_data.non_const(); }
     Data & m_data;
};

int main()
{
    Data data;
    const Image img(data);
    img.check();

    return 0;
}

So then in order to obtain the behavior where it could accept a const-ref and store it as const-ref, the effective declaration of the reference would have to change to be const. This would then mean that it would be a completely distinct type, NOT a const version of the original type (since two types with members differing in const-qualification are treated as two separate types in C++). Thus, either the compiler has to be able to do excessive behind-the-scenes magic to convert these things back and forth, remembering the const-ness of the members, or it has to treat it as a separate type which then couldn’t be used in place of the normal type.

I think what you’re trying to achieve is a referencee_const object, a concept that only exists in C++ as a separate class (which I suspect could be implemented with judicious use of templates although I didn’t make an attempt).

Is this strictly a theoretical question (answer: C++ decided to split object and referencee constness) or is there an actual practical uncontrived problem you’re trying to solve?

Leave a Comment