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.
La 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
".
Autres conseils
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.