From: Mathieu Lacage on
hi,

The code below fails to compile with my g++ 4.1.1:

class Base
{
public:
virtual ~Base () = 0;
};
Base::~Base () {}
class Derived : public Base
{
public:
virtual ~Derived () {}
};

void Do (const Base &base)
{}

class A
{
public:
operator Derived () const {return Derived ();}
};


int main (int argc, char *argv[])
{
Derived derived = A ();
const Base &base = A ();
Do (A ());

return 0;
}

with the following error:
test.cc: In function 'int main(int, char**)':
test.cc:27: error: cannot allocate an object of abstract type 'Base'
test.cc:2: note: because the following virtual functions are pure within
'Base':
test.cc:6: note: virtual Base::~Base()

Which points to the line which calls function Do (A ()). I have to confess
that I am a bit fumbled by this: I would have expected the line above
const Base &base = A (); to also fail or to have both lines not fail.

Anyhow, the question then is to know whether there is a way to make this
code to compile and run to allow the compiler a way to guess the right
type conversion when calling Do (const Base &). I could, of course, make A
derive from Base but this (A) class (in my code) is really not expected to
be polymorphic so, it kind of defeats the whole purpose of the exercise.

Any hints ?

regards,
Mathieu

--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

From: Jiri Palecek on
Mathieu Lacage wrote:

> hi,

Hi

> The code below fails to compile with my g++ 4.1.1:

....
>
> Which points to the line which calls function Do (A ()). I have to confess
> that I am a bit fumbled by this: I would have expected the line above
> const Base &base = A (); to also fail or to have both lines not fail.
>
> Anyhow, the question then is to know whether there is a way to make this
> code to compile and run to allow the compiler a way to guess the right
> type conversion when calling Do (const Base &). I could, of course, make A
> derive from Base but this (A) class (in my code) is really not expected to
> be polymorphic so, it kind of defeats the whole purpose of the exercise.
>
> Any hints ?

This is really interresting, because it compiles with Intel C++ compiler.
However, the way I read 8.5.3, it should be impossible to initialize const
Base& with A(), because the standard says

... a temporary of type cv1 T1 is created ...

and T1 would be Base in this case, and there cannot be any temporary of type
const Base.

If you really want to use the conversion operator, you can invoke it
explicitly

Do((Derived)A());

however, I would prefer an explicit conversion function (like
A().toDerived())

The question is, why does the standard allow implicit conversions like

A -> const Derived& -> const Base&

provided there's a conversion operator to const Derived& in A, and not

A -> Derived -> const Base&

when there's a conversion operator to Derived in A.

Is that a defect or is there a reason for it?

Regards
Jiri Palecek


--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

From: Alberto Ganesh Barbati on
Mathieu Lacage ha scritto:
> hi,
>
> The code below fails to compile with my g++ 4.1.1:
>
> class Base
> {
> public:
> virtual ~Base () = 0;
> };
> Base::~Base () {}
> class Derived : public Base
> {
> public:
> virtual ~Derived () {}
> };
>
> void Do (const Base &base)
> {}
>
> class A
> {
> public:
> operator Derived () const {return Derived ();}
> };
>
>
> int main (int argc, char *argv[])
> {
> Derived derived = A ();
> const Base &base = A ();
> Do (A ());
>
> return 0;
> }
>
> with the following error:
> test.cc: In function 'int main(int, char**)':
> test.cc:27: error: cannot allocate an object of abstract type 'Base'
> test.cc:2: note: because the following virtual functions are pure within
> 'Base':
> test.cc:6: note: virtual Base::~Base()
>
> Which points to the line which calls function Do (A ()). I have to confess
> that I am a bit fumbled by this: I would have expected the line above
> const Base &base = A (); to also fail or to have both lines not fail.

Looks like a bug in g++ to me. According to my interpretation of 8.5.3/5
both lines are ill-formed, because this rule applies:

"a temporary of type �cv1 T1� is created and initialized from the
initializer expression using the rules for a non-reference copy
initialization (8.5)"

(where T1 is Base). Of course you cannot create a temporary of type Base
because it's an abstract class. The funny thing is that g++ 3.4.5 agrees
with my interpretation and chokes on both lines.

>
> Anyhow, the question then is to know whether there is a way to make this
> code to compile and run to allow the compiler a way to guess the right
> type conversion when calling Do (const Base &). I could, of course, make A
> derive from Base but this (A) class (in my code) is really not expected to
> be polymorphic so, it kind of defeats the whole purpose of the exercise.
>
> Any hints ?
>

The main problem here is that the A is only convertible to an rvalue of
type Derived. If it could be made convertible to an *lvalue* of type
Derived, then a different rule would apply, i.e.: the reference
would bound directly to the lvalue result of the conversion.

For example with this definition of A:

class A
{
public:
operator const Derived& () const
{
static Derived d;
return d;
}
};

both lines compile correctly.

HTH,

Ganesh


--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]