I stumbled upon something the other day in the code of a colleague and I want to understand how/why this works.
He uses a struct like this
struct my_struct
{
my_struct(){ /* default constructor*/};
my_struct(char c){ /*some special constructor*/};
// other stuff
my_struct& operator=(const my_struct &ms){ /* assignment */};
};
Originally through a typo he figured out that the following works
my_struct ms;
double a;
ms = a;
I have worked out that this is equal (in the sense of gives the same final struct ms) to the following
my_struct ms;
double a;
my_struct ms2((char) a);
ms=ms2;
But I don't know why. Personally, I think this should not work, because there is no assign operator for double and my_struct and additionally because there is no constructor for my_struct using a double.
I tried to google this, but did not find anything relevant.
@ user657267: i wanted to keep it as short as possible, you could add a line a=5; or whatever the same would apply.
During the compilation this:
ms = a;
attempts to resolve an assignment of one or more of the following immediate forms
my_struct& operator ()(double)
my_struct& operator ()(double&)
my_struct& operator ()(const double&)
and a litany of other potential conversion from double
. And none is found. In fact, only the following is discovered:
my_struct& operator=(const my_struct &ms)
which indicates the compiler does allow assignment via a const-reference of another my_struct
. At that time a conversion constructor is sought, starting with the most immediate conversion (explicit to the type double
:
my_struct(double)
my_struct(double&)
my_struct(const double&)
It is important to note such a constructor cannot mandate explicit use. We're implicitly constructing a temporary, and as such explicit mandate is off the reservation.
Anyway, again, none is found. Before giving up the compiler attempts to locate a constructor of any form that can convert from double
to whatever the fundamental construction requires and said constructor supports implicit construction. In effect, something of the form
my_struct(<<something that can be converted from a double>>)
And again, the constructor cannot be explicit
. As it turns out, this search does find this:
my_struct(char)
because double
can be converted to char
(albeit poorly and likely not what you want). The entire chain is a little (ok, a lot) more complicated than that, but that is the crux of it.
You can avoid this implicit construction by ensuring that constructor is only explicit
in usage, but that is a double-edge sword, so care is required. Use of explicit
can be somewhat harsh. Doing this:
explicit my_struct(char)
will squelch the unintended implicit construction when converting double
to char
. But I warn you; it will also squelch the ability to do this:
char x = 'a';
my_struct ms;
ms = x;
because now my_struct
cannot be implicitly constructed at all from char
, by conversion or otherwise. There are multiple ways around this, including defining a specific assignment operator for the type (takes a double
) or a specific conversion constructor (takes a double
). How you approach that I leave to you.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With