Reputation:
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
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:
doJob
is an error for a default constructed object, then why not dis-allow such invalid state?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