user10311305
user10311305

Reputation:

How to define some constructors as for not-constant objects only?

Having a following class:

class Foo {
public:
  Foo() : m_data{std::nullopt} {} // this is fine (not having m_data set), 
                                  // but only at the beginnig of objects lifetime
  Foo(Bar data) : m_data{data} {}

  void setData(Bar newData);
  Bar getData() const;

  void doJob() const; // requires m_data to be set (not std::nullopt)
  void doOtherJob() const; // does not require m_data to be set.
  /*...*/

private:
  std::optional<Bar> m_data;

At the beginnig, there is a possibility of having m_data not set, but only to the point of first setData() call, then m_data will never ever go back to being empty (std::nullopt)

My question is, can I somehow tell the compiler to never allow constructing objects of type Foo with the first constructor (default one: Foo()) if those objects are marked as const so that there will be no chance for this type of code:

const Foo x;           // without const totally fine
// x.setData( Bar{} ); // but with it, setData cannot be called
x.doJob();             // which makes that call a 100% throw error
                       // and in general, whole object is less usefull now
                       // because it is constructed only partially, 
                       // and cannot be finished 

to pass compilation stage?

Final efect should look like this:

Bar data = getSomeData();

Foo a;             // fine
Foo b{data};       // fine
const Foo c;       // error, this type will never be usefull / is artificially limited, 
                   // no logical reason to make it const
const Foo d{data}; // fine

Is there any way to get at compile time information about const'ness of a given new object (in objects class construction code or definition), so that I could use SFINAE or something else to split, distinguish diffrent construction routines for const and not-const objects?

I want it to be done at compile-time.

It would be nice to be able to just write something like:

class Foo{
public:
                                    // both can still mutate everything
  Foo() { /*...*/ }                 // but this one cant be called by const objects            
  Foo(Bar data) const { /*...*/ }   // and this one can
};

which would not try to make this pointer const Foo* but only pretend like it, so const objects could not call this first "method", but that is not allowed to what I know & checked up to this point.

(type Bar cannot be set to some sort of default value, null value. It either is, or not, and I would like to keep it that way)

I also don't know why it is not possible to mark constructors with const, because then (in my opinion) there would be no problem with all those classes where objects can be constructed partially, but after still have to be fulfilled completely in order to work properly or work in its potential.

I couldn't find any other programmer with same issue so I bringed up extended code sample to check is it really a problem (having different approach for creation of const objects) or do I just simply do things in a wrong way. Is there any design pattern, style of programming, etc. that I'm missing and which makes those problems not existing?

I know that at run-time there is no difference between const and not-const objects but that's not the point. I believe this problem can be solved at compile-time, i just don't know how to tell a compiler what I have in mind.

Edit: making an object with Foo() is useful (using only a part of its functionality), but only if later it will do its main job which requires m_data.

Upvotes: 2

Views: 94

Answers (1)

eerorika
eerorika

Reputation: 238401

No, it is not possible to know in the constructor whether the object will be const or non-const. So, your desired functionality is not possible to implement. You have two options:

  • Remove the default constructor. If doJob is an error for a default constructed object, then why not dis-allow such invalid state?
  • Accept the fact that const Foo c; is useless, but the compiler will not tell the programmer. The programmer should find this out quite soon if they test the code that they write. The uselessness should also become quite clear from the documentation of the class.

Upvotes: 2

Related Questions