Mark constructor as __explicitly__ requiring an object type
-
11-03-2021 - |
Question
I have a constructor that accepts an object of type Material
:
SomeClass::SomeClass( const Material& mat ) ;
However, Material
allows construction by a Vector
:
Material::Material( const Vector& v ) ;
Therefore, SomeClass
can allow construction by a Vector
:
SomeClass m( vec ) ; // valid, since vec is constructed to a Material first,
// then is passed to the SomeClass(Material) ctor
However, after "shooting myself in the foot" more than once with ctors of this type (in different classes in the same project!) I want to disallow construction of SomeClass
by Vector
objects directly, instead always requiring a Material
to be passed instead.
Is there a way to do this? Somehow think it has to do with the explicit
keyword.
Solution
You cannot do this without interfering with your ability to transparently construct Material
from Vector
.
If you make Material
's constructor explicit
explicit Material( const Vector& v ) ;
then you will always have to write Material(v)
in order to construct an instance. This will prevent you from instantiating SomeClass
with a Vector
accidentally, but it will also break all expressions that evaluate to a Vector
where a Material
is expected.
This makes sense, because by not declaring the constructor explicit
you are saying "a Vector
is just as good as a Material
no matter what the context". You cannot then do a half-step backward and say "oh, well, except when constructing a SomeClass
".
OTHER TIPS
You declare Material(const Vector &v)
to be explicit
; this prevents implicit conversion from one to the other.
This, of course, is not a specific restriction on SomeClass
; it's a global ban on any instance of an implicit conversion.
Make the constructor of Material
explicit
:
explicit Material(const Vector& v) { ... }
Or if you don't want to do that, as a bit of a hack and with const
-correctness as a sacrifice, remove the const
from const Material& mat
. You won't be able to pass a temporary object to the constructor for SomeClass
(or a const
instance which may be too big a sacrifice). However, that keeps you from doing SomeClass(Material(v))
which you may want to do. So you can only get close to what you want, but I'm afraid that it's not completely possible.