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.
Nope, the standard does not differentiate the cases like that.
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.
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:
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
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: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