By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
424,681 Members | 1,854 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 424,681 IT Pros & Developers. It's quick & easy.

Conversion: via constructor or operator

P: n/a
Hi,

I have a question regarding the conversion of objects. When is the
conversion done by the constructor and when by the operator. My feeling
tells me that the constructor is preferred. But I couldn't find the
exact rule in the C++ standard.

And what if the classes have template parameters?

It would be great if somebody could get me a rough hint where in the
standard I should start reading.

I know that it is dangerous to have both a conversion constructor and a
conversion operator. But I want to learn more about this whole
mechanism.

Thanks,
Michael

//---------------------------------------
struct A;

struct B
{
B(const A &a);
};

struct A
{
operator B() const {}
};

B::B(const A &a) {}

int
main()
{
A a;
B b = a; // Uses always the constructor of B if possible?
return 0;
}
//----------------------------------------
Oct 30 '05 #1
Share this Question
Share on Google+
7 Replies


P: n/a
* Michael Lehn:
Hi,

I have a question regarding the conversion of objects. When is the
conversion done by the constructor and when by the operator. My feeling
tells me that the constructor is preferred.
If you mean, should you implement a conversion by providing a
constructor, or by providing an operator, then sometimes that is
clearcut, and sometimes it's personal preference.

If you mean, can one be called preferentially if both are defined, then
no, not in a conforming implementation.

A conforming compiler will reject such code.

But I couldn't find the exact rule in the C++ standard.

And what if the classes have template parameters?

It would be great if somebody could get me a rough hint where in the
standard I should start reading.

I know that it is dangerous to have both a conversion constructor and a
conversion operator. But I want to learn more about this whole
mechanism.
It's not dangerous: it's just not allowed.

//---------------------------------------
struct A;

struct B
{
B(const A &a);
};

struct A
{
operator B() const {}
};

B::B(const A &a) {}

int
main()
{
A a;
B b = a; // Uses always the constructor of B if possible?
return 0;
}
//----------------------------------------


MSVC 7.1 incorrectly compiles this. g++ 3.4.4 rejects it, correctly.
Comeau 4.3.3 (huh, what's with those numbers?) rejects it, correctly.

--
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?
Oct 30 '05 #2

P: n/a
Alf P. Steinbach wrote:
* Michael Lehn:
Hi,

I have a question regarding the conversion of objects. When is the
conversion done by the constructor and when by the operator. My feeling
tells me that the constructor is preferred.


If you mean, should you implement a conversion by providing a
constructor, or by providing an operator, then sometimes that is
clearcut, and sometimes it's personal preference.

If you mean, can one be called preferentially if both are defined, then
no, not in a conforming implementation.

A conforming compiler will reject such code.

But I couldn't find the exact rule in the C++ standard.

And what if the classes have template parameters?

It would be great if somebody could get me a rough hint where in the
standard I should start reading.

I know that it is dangerous to have both a conversion constructor and a
conversion operator. But I want to learn more about this whole
mechanism.


It's not dangerous: it's just not allowed.

//---------------------------------------
struct A;

struct B
{
B(const A &a);
};

struct A
{
operator B() const {}
};

B::B(const A &a) {}

int
main()
{
A a;
B b = a; // Uses always the constructor of B if possible?
return 0;
}
//----------------------------------------


MSVC 7.1 incorrectly compiles this. g++ 3.4.4 rejects it, correctly.
Comeau 4.3.3 (huh, what's with those numbers?) rejects it, correctly.


But gcc 4.0 does compile this program which suggests that gcc 3.4.4's
failure to compile this program was an error. And a close reading of
the Standard certainly provides no reason why there should be an error
in this case. There is only one user-defined conversion that could
match B b = a, and it is not the one selected by the overload
resolution as the best match anyway.

Since B's constructor accepts a const A& parameter, the variable, a,
used to initialize b in

B b = a;

is an "exact match" for the type needed to construct a B object
directly. No conversion takes place: a is passed to B's constructor, as
is. If that were not the case, and the initializer, a, had to be
converted to some other type in order to match the type of parameter
declared in B's constructor, then there would exist two user-defined
conversions that could be invoked to construct b. And if one of those
conversion sequences were to be selected as the best match then at that
point an ambiguous conversion error would be reported.

Greg

Oct 31 '05 #3

P: n/a
* Greg:
Alf P. Steinbach wrote:
* Michael Lehn:
Hi,

I have a question regarding the conversion of objects. When is the
conversion done by the constructor and when by the operator. My feeling
tells me that the constructor is preferred.
If you mean, should you implement a conversion by providing a
constructor, or by providing an operator, then sometimes that is
clearcut, and sometimes it's personal preference.

If you mean, can one be called preferentially if both are defined, then
no, not in a conforming implementation.

A conforming compiler will reject such code.

But I couldn't find the exact rule in the C++ standard.

And what if the classes have template parameters?

It would be great if somebody could get me a rough hint where in the
standard I should start reading.

I know that it is dangerous to have both a conversion constructor and a
conversion operator. But I want to learn more about this whole
mechanism.


It's not dangerous: it's just not allowed.

//---------------------------------------
struct A;

struct B
{
B(const A &a);
};

struct A
{
operator B() const {}
};

B::B(const A &a) {}

int
main()
{
A a;
B b = a; // Uses always the constructor of B if possible?
return 0;
}
//----------------------------------------


MSVC 7.1 incorrectly compiles this. g++ 3.4.4 rejects it, correctly.
Comeau 4.3.3 (huh, what's with those numbers?) rejects it, correctly.


But gcc 4.0 does compile this program which suggests that gcc 3.4.4's
failure to compile this program was an error. And a close reading of
the Standard certainly provides no reason why there should be an error
in this case.


You need to read even closer...

There is only one user-defined conversion that could
match B b = a, and it is not the one selected by the overload
resolution as the best match anyway.

Since B's constructor accepts a const A& parameter, the variable, a,
used to initialize b in

B b = a;

is an "exact match" for the type needed to construct a B object
directly.
The B object is not constructed directly except after optimization, and
that _possible_ optimization does not affect which rules are in play;
formally 'b' is here copy-constructed from a B object.

It would be different if the OP had used direct initialization (the C++
initialization syntax).

Then you'd have an exact match.

No conversion takes place: a is passed to B's constructor, as
is. If that were not the case, and the initializer, a, had to be
converted to some other type in order to match the type of parameter
declared in B's constructor, then there would exist two user-defined
conversions that could be invoked to construct b.
Yes, that's the situation here. 'a' must be converted to a B, which is
then passed to B's copy constructor. There are two ways to convert 'a'
to a B in a single step, hence the conversion is ambigious.

And if one of those
conversion sequences were to be selected as the best match then at that
point an ambiguous conversion error would be reported.


That's what a conforming compiler such as Comeau does.
PS: It would be nice if you could report the bug in g++ 4.0!

--
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?
Oct 31 '05 #4

P: n/a
Alf P. Steinbach wrote:
And if one of those
conversion sequences were to be selected as the best match then at that
point an ambiguous conversion error would be reported.


That's what a conforming compiler such as Comeau does.


struct A;
struct B { B() {} B(const A &a) {} };
struct A { operator B() const { return B(); } };

int main()
{
A a;
B b = a;
}

Strange, Comeau 4.3.3 actually compiles this code fine. It does not
compile the original code, but this is only because the body of
"operator B() const" is empty, which is a completely different error.

--

Valentin Samko - http://www.valentinsamko.com

Oct 31 '05 #5

P: n/a
* Valentin.Samko:
Alf P. Steinbach wrote:
And if one of those
conversion sequences were to be selected as the best match then at that
point an ambiguous conversion error would be reported.
That's what a conforming compiler such as Comeau does.


struct A;
struct B { B() {} B(const A &a) {} };
struct A { operator B() const { return B(); } };

int main()
{
A a;
B b = a;
}

Strange, Comeau 4.3.3 actually compiles this code fine.


Sorry, you're wrong.

Comeau 4.3.3 does not compile your code, even in non-strict mode.

You can try it out at <url: http://www.comeaucomputing.com/tryitout/>.

Comeau C/C++ 4.3.3 (Aug 6 2003 15:13:37) for ONLINE_EVALUATION_BETA1
Copyright 1988-2003 Comeau Computing. All rights reserved.
MODE:non-strict warnings C++

"ComeauTest.c", line 8: error: more than one user-defined conversion
from "A" to "B"
applies:
function "A::operator B() const"
function "B::B(const A &)"
B b = a;
^

1 error detected in the compilation of "ComeauTest.c".

It does not
compile the original code, but this is only because the body of
"operator B() const" is empty, which is a completely different error.


Sorry, you're wrong.

--
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?
Oct 31 '05 #6

P: n/a
Alf P. Steinbach wrote:
Strange, Comeau 4.3.3 actually compiles this code fine. Sorry, you're wrong.

It compiles this code fine using vc++7.1 as a backend, without --strict.
Why would I write this if it didn't compile the code for me?
Comeau 4.3.3 does not compile your code, even in non-strict mode. It does, using vc7.1 as a backend.
You can try it out at <url: http://www.comeaucomputing.com/tryitout/>. I just used my copy.
como --vc71 0.cpp como: Warning: COMO_MS_INCLUDE environment variable missing
Comeau C/C++ 4.3.3 (Jan 13 2004 11:29:09) for MS_WINDOWS_x86
Copyright 1988-2003 Comeau Computing. All rights reserved.
MODE:non-strict warnings microsoft C++aout

It does not
compile the original code, but this is only because the body of
"operator B() const" is empty, which is a completely different error.

Sorry, you're wrong.

Again, this depends on the backend compiler and options. I am quite right according to my
copy of comeau, using default options.

--

Valentin Samko - http://www.valentinsamko.com
Oct 31 '05 #7

P: n/a
* Valentin Samko:
Alf P. Steinbach wrote:
Strange, Comeau 4.3.3 actually compiles this code fine.

Sorry, you're wrong.

It compiles this code fine using vc++7.1 as a backend, without --strict.
Why would I write this if it didn't compile the code for me?
Comeau 4.3.3 does not compile your code, even in non-strict mode.

It does, using vc7.1 as a backend.


Grumble.

Anyway, the code's formally incorrect.

--
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?
Oct 31 '05 #8

This discussion thread is closed

Replies have been disabled for this discussion.