Question regarding copy constructor

A

Alf P. Steinbach

Here Tobias probably meant

A a(( A(b) ));

which declares an object rather than a function (it's the so called
"most vexing parse" in action). A a(A(2)) declares an object because it
cannot be parsed as a function declaration. But A a(A(b)) can be parsed
as a function declaration, and so that's what's assumed...

I would have posted this clarification except I don't see his postings,
after he engaged in a bit of attempted character assassination when he
(I presume) felt that he lost the technical argument. Tobias: that's
what a "plink" or "plonk" means (the former is for light-weight trolls,
the sound of the troll hitting the inner surface of toilet). Google it.

I think you're probably right about this. (At least
it sounds good.)

Nope, the standard does not differentiate the cases like that.

Just to be clear, what I think you're saying is that
if the conversion operator:

B::eek:perator A()

exists, but the constructor:

A::A(B)

does not, then (as currently defined)

A a = b;

will work, because the conversion operator exists,
but if we defined A a = b; to be exactly synonymous
with direct initialization, then it would fail,
because the necessary constructor doesn't exist.

Is that right?

(Perhaps I will take a look at the standard and/or
write a test program to sort this out.)

Always a good idea. :)

However, g++ (and probably "therefore" also clang, which was aimed to be
a drop-in replacement) has a bug in this respect.

Visual C++ 12.0 behaves correctly, though.

By the way, this may be relevant to the recent post
"Understanding copy construction ambiguity" on our
moderated companion group:

https://groups.google.com/forum/?fromgroups#!topic/comp.lang.c++.moderated/-5pL9ywO29Y

Perhaps somebody who understands this better than I
do could shed some light on that fellow's question.

First, what the Holy Standard says about the case of copy construction
of an object of class type T, when the initializer is not of type T or a
type derived from T:

C++11 §8.5/15 sixth dash second subdash:
user-defined conversion sequences that can convert from the source type
to the destination type or (when a conversion function is used) to a
derived class thereof are enumerated as described in 13.3.1.4, and the
best one is chosen through overload resolution (13.3). If the conversion
cannot be done or is ambiguous, the initialization is ill-formed. The
function selected is called with the initializer expression as its
argument; if the function is a constructor, the call initializes a
temporary of the cv-unqualified version of the destination type. The
temporary is a prvalue. The result of the call (which is the temporary
for the constructor case) is then used to direct-initialize, according
to the rules above, the object that is the destination of the
copy-initialization. In certain cases, an implementation is permitted to
eliminate the copying inherent in this direct-initialization by
constructing the intermediate result directly into the object being
initialized; see 12.2, 12.8.

The "then used to direct-initialize" means A a(( A(initializer) )).

Now re the clc++m question, the OP is being misled by a faulty compiler.
As you can see above, it's not the case that copy initialization
considers only a restricted set of conversion (which is what the OP's
compiler does). And happily, Visual C++ diagnoses both cases as
ambiguous, so that we can see that compilers disagree (it's much worse
when all available compilers agree on incorrect behavior).


Cheers & hth.,

- Alf
 
J

James Kanze

Ok, that makes perfect sense without tools that can warn about likely
most vexing parse. How often does anyone actually want to declare a
function in other function's body?

The most vexing parse doesn't only occur within a function body.
The exact same problems occur at namespace scope. The only
difference is that often, at namespace scope, we want the
declaration to be considered a function declaration. But when
we don't, all of the same issues raise their head.
I have had very close to zero
occasions of such desire. So most vexing parse is accidental usage
of useless feature and a tool that underlines it with red does
not take any rocket science to develop.

But it should probably only do so in block scope, because
function declarations at namespace scope _are_ frequent.
 
Ö

Öö Tiib

The most vexing parse doesn't only occur within a function body.
The exact same problems occur at namespace scope. The only
difference is that often, at namespace scope, we want the
declaration to be considered a function declaration. But when
we don't, all of the same issues raise their head.

You are correct of course that it is not always clear what "we" want. Some
people may want lot of namespace level variables. I need them next to
none and suspect that those more hurt than aid. -Wvexing-parse of clang
works well enough for me.
But it should probably only do so in block scope, because
function declarations at namespace scope _are_ frequent.

I also think so. Namespace scope is fortunately less hard to differentiate
from function scope than for example a type from a variable.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,016
Latest member
TatianaCha

Latest Threads

Top