Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

C++ Constructor : silent amiguity

20 views
Skip to first unread message

m.laba...@gmail.com

unread,
Nov 17, 2018, 1:49:16 PM11/17/18
to
Hi,

How to force gcc to complain about ambiguity.

Following there is example:

--{beg:main.cpp}---------------------------------
#include <iostream>
class A {
public:
A() : x(new int) { *x = 0; }
virtual ~A() { delete x; }
virtual void run() { std::cout << (void *)this << ":" << *x << std::endl; }
private:
int * x;
};
class B : public A {
public:
B(A & a) : a(a) { }
virtual void run() { a.run(); }
private:
A & a;
};
int main(void) {
A a;

A other;
B b(other);

a.run();
b.run();

A * ptrA = new B(a);
#if 1 // wrong
A * ptrB = new B(b); // <------ this is the point of issue
// simple allocation and copy Memory is executed
// instead of defined Constructor
#else // good
A * ptrB = new B(static_cast<A &>(b));
#endif

ptrA->run();
ptrB->run();

delete ptrB;
delete ptrA;

return 0;
}
--{eof:main.cpp}---------------------------------

Copy constructor is not defined, so simple copy operation is available.
But there exists a Constructor which matches passed arguments.

Regards

--
Maciej Labanowicz

Alf P. Steinbach

unread,
Nov 17, 2018, 3:05:59 PM11/17/18
to
C++17 §15.8.1/6:
<quote>
If the class definition does not explicitly declare a copy constructor,
a non-explicit one is declared implicitly. If the class definition
declares a move constructor or move assignment operator, the implicitly
declared copy constructor is defined as deleted; otherwise, it is
defined as defaulted (11.4). The latter case is deprecated if the class
has a user-declared copy assignment operator or a user-declared destructor.
</quote>

Essentially, you can't have a class without a copy constructor
declaration. Either it's declared in the source code, or it's declared
implicitly.

And the defaulted copy constructor in class B is a better match for
lvalue argument of type B.

If you add

B(const B &) = delete;

... then the result isn't that it's disregarded, but that the compiler
complains about the attempt to use a deleted function.

A working remedy is to instead add

B(B & b): a(b) {}

But to cover all cases, better do

template< class T > B(T & o): a(o) {}

Oh, B(T & o ). BTO, as you're probably well aware, was a Canadian rock
group in the 1970's, Bachman Turner Overdrive, who enjoyed immense
success with a nonsense song where the singer stuttered “You you you
ain't seen no no no nothing yet!”.

It was not intended. In fact they re-recorded to get rid of the
stuttering. But the record company insisted on including it on an album,
and so they got their only super-hit on the music charts.

I think it's that way with C++ syntax also, that much is unintended.

Cheers!,

- Alf
0 new messages