Can a C++ constructor know whether it's constructing a const object?
Asked Answered
V

2

8

In C++, object constructors cannot be const-qualified.

But - can the constructor of an object of class A know whether it's constructing a const A or a non-const A?

Motivated by a fine point in the discussion regarding this question.

Vedis answered 2/7, 2021 at 15:46 Comment(7)
That discussion lead me to write this. Looks like gcc zeros out the buffer afterwards for some reason. Nerd Sniping is a thing!Overman
For your use case, is a constructor enum Tag { Mut, Const }; acceptable? So you'd do Foo foo{Mut}; or Foo const cfoo{Const}; ... which means it's manual, and if someone messes up it'll be annoying to track down the mistake.Contumely
@AyxanHaqverdili: I'm not sure how that program relates to the question, but - if I am not mistaken, reading from where an object has been destructed is undefined behavior.Vedis
@Eljay: Obviously if you tell your constructor what you're constructing, it can tell you right back. No cheating...Vedis
@Vedis the relation was to change buffer only using a const pointer.Overman
I don't think the constructor knows if the object is being born const. You can mutate the member variables in the body of the constructor. If there was a Foo() const { ... } constructor, then that would be the hook. So I think you'll need to cheat, or double-down cheat and use a MACRO. Or take a page out of JavaScript, and add a freeze() method that sets a flag which is vetted for mutating methods and throws if tripped.Contumely
The answer that was deleted which used passing a pointer of the object into the constructor needs a catchy name. I propose CUCP "Curiously Uncommon Constructor Pattern". Regarding Ayxan's Nerd Sniping: programmers are only worth one point.Contumely
V
0

Actually, a constructor never constructs a const object. The object is not const during construction, in the sense that the constructor code is allowed to change the object. If you call methods from within the constructor - they will be the non-const variants of methods.

Thus, in this code:

struct A {
    int foo() const { return 123; }
    int foo()       { return 456; }
    A() { x = foo(); }
    int x;
};

int bar() {
    A a;
    return a.x;
}

int baz() {
    A const a;
    return a.x;
}

both fnctions, bar() and baz(), return 456 - according to all major compilers (GodBolt).

What happens with the constructed object is simply not the constructor's business.

Vedis answered 27/8, 2024 at 14:32 Comment(0)
P
4

No, because copy elision (and the so-called guaranteed copy elision) can change the constness of an object "after" construction:

struct A {
  bool c;
  A() : c(magic_i_am_const()) {}
  A(const A&)=delete;      // immovable
};

const A f() {return {};}
A g() {return f();}        // OK
void h() {
  A x=f();                 // OK
  const A y=g();           // OK
}

What should x.c and y.c be?

Pianette answered 2/7, 2021 at 20:13 Comment(2)
Your example is a bit boring, since x and y are created only once (by variable definition) and thus their constness doesn't change.Golly
@LanguageLawyer: I figured it was clearer to illustrate with prvalues, which have but one set of semantics, even though it’s hard to say what the constness of an unmaterialized prvalue means. If you switch to NRVO, you (can) get multiple non-reference variables with different cv-qualifications that are all the same object, although one could argue that that’s not quite “changing” either.Pianette
V
0

Actually, a constructor never constructs a const object. The object is not const during construction, in the sense that the constructor code is allowed to change the object. If you call methods from within the constructor - they will be the non-const variants of methods.

Thus, in this code:

struct A {
    int foo() const { return 123; }
    int foo()       { return 456; }
    A() { x = foo(); }
    int x;
};

int bar() {
    A a;
    return a.x;
}

int baz() {
    A const a;
    return a.x;
}

both fnctions, bar() and baz(), return 456 - according to all major compilers (GodBolt).

What happens with the constructed object is simply not the constructor's business.

Vedis answered 27/8, 2024 at 14:32 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.