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

conversion to non-scalar type error in inheritance hierarchy

10 views
Skip to first unread message

kmw

unread,
Oct 29, 2009, 11:20:21 AM10/29/09
to
Hello,

I am working on container class with different implementations and
want to add stl-style iterators. Now, I am confronted with a
"conversion to non-scalar type" error which I do not understand. Any
comments are appreciated. Many thanks in advance!

The interface for the different implementations is defined in the base
class A. A1 is one implementation. B is the iterator base class and C
its implementation in A1. I really do not see a problem since C
inherits from B but the compiler says:

test.cpp: In function ‘int main()’:
test.cpp:34: error: conversion from ‘A<int>::B’ to non-scalar type
‘A1<int>::C’ requested

Best regards,
Kay

Code:
template <class X>
class A
{
public:
class B
{
public:
virtual ~B () {}
virtual void method () {}
};
virtual ~A () {}
virtual B begin ()=0;
};
template <class X>
class A1 : public A<X>
{
public:
class C : public A<X>::B
{
public:
~C () {}
void method ( ) {}
};
~A1 () {}
typename A<X>::B begin ( )
{
C test;
return test;
}
};
int main ( )
{
A1<int> test;
A1<int>::C test_it = test.begin ();

return 0;
}

Victor Bazarov

unread,
Oct 29, 2009, 11:29:30 AM10/29/09
to
kmw wrote:
> Hello,
>
> I am working on container class with different implementations and
> want to add stl-style iterators. Now, I am confronted with a
> "conversion to non-scalar type" error which I do not understand. Any
> comments are appreciated. Many thanks in advance!
>
> The interface for the different implementations is defined in the base
> class A. A1 is one implementation. B is the iterator base class and C
> its implementation in A1. I really do not see a problem since C
> inherits from B but the compiler says:
>
> test.cpp: In function �int main()�:
> test.cpp:34: error: conversion from �A<int>::B� to non-scalar type
> �A1<int>::C� requested

You do not see the problem? How about here:

class B {};
class C : public B {};

B foo();

int main()
{
C c = foo();
}

Do you get the same error?

There is no conversion from the base class to the derived class. You
have to define this conversion if you want it to exist.

V
--
Please remove capital 'A's when replying by e-mail
I do not respond to top-posted replies, please don't ask

kmw

unread,
Oct 29, 2009, 11:42:49 AM10/29/09
to
Well, yes. Your code gives me the same error. I see the conversion
problem now. Thanks for clarifying. Of course I don't want explicit
conversion from the base class into the inherited classes. But how can
I achieve such kind of "parallel" inheritance? That is, 'C' is
accepted as 'B' in 'A1'. I know I could do it with reference returns
but that's not in accordance to the stl-iterator approach.

Cheers,
Kay

On Oct 29, 4:29 pm, Victor Bazarov <v.Abaza...@comAcast.net> wrote:
> kmw wrote:
> > Hello,
>
> > I am working on container class with different implementations and
> > want to add stl-style iterators. Now, I am confronted with a
> > "conversion to non-scalar type" error which I do not understand. Any
> > comments are appreciated. Many thanks in advance!
>
> > The interface for the different implementations is defined in the base
> > class A. A1 is one implementation. B is the iterator base class and C
> > its implementation in A1. I really do not see a problem since C
> > inherits from B but the compiler says:
>

> > test.cpp: In function ‘int main()’:
> > test.cpp:34: error: conversion from ‘A<int>::B’ to non-scalar type

> > ‘A1<int>::C’ requested

Alf P. Steinbach

unread,
Oct 29, 2009, 11:43:28 AM10/29/09
to
* kmw:

> Hello,
>
> I am working on container class with different implementations and
> want to add stl-style iterators.

It may be easiest to write a templated wrapper that uses some underlying
conventional named methods interface to provide STL iterator functionality.


> Now, I am confronted with a
> "conversion to non-scalar type" error which I do not understand. Any
> comments are appreciated. Many thanks in advance!
>
> The interface for the different implementations is defined in the base
> class A. A1 is one implementation. B is the iterator base class and C
> its implementation in A1. I really do not see a problem since C
> inherits from B but the compiler says:
>

> test.cpp: In function �int main()�:
> test.cpp:34: error: conversion from �A<int>::B� to non-scalar type

> �A1<int>::C� requested


>
> Best regards,
> Kay
>
> Code:
> template <class X>
> class A
> {
> public:
> class B
> {
> public:
> virtual ~B () {}
> virtual void method () {}
> };
> virtual ~A () {}
> virtual B begin ()=0;
> };
> template <class X>
> class A1 : public A<X>
> {
> public:
> class C : public A<X>::B
> {
> public:
> ~C () {}
> void method ( ) {}
> };
> ~A1 () {}
> typename A<X>::B begin ( )
> {
> C test;
> return test;
> }

Not related to the compilation error, but a logical error: this begin() function
always produces an A<X>::B object. It doesn't matter that that object is
initialized from a C object. When it's returned it's a B object, and calls to
method will invoke B::method.


> };
> int main ( )
> {
> A1<int> test;
> A1<int>::C test_it = test.begin ();

test.begin() produces a B object. Class C does not provide any constructor that
takes a B object. A B object cannot be implicitly converted down to the more
specialized C object (the inheritance goes the wrong way).


>
> return 0;
> }


Cheers & hth.,

- Alf

kmw

unread,
Oct 29, 2009, 11:47:58 AM10/29/09
to
> It may be easiest to write a templated wrapper that uses some underlying
> conventional named methods interface to provide STL iterator functionality.

Thanks for the hint. Could you give a small code snippet to ease my
understanding? That would be great!

I see the problem with the inheritance 'in the wrong way' now. Also,
thanks for this.

Cheers,
Kay

On Oct 29, 4:43 pm, "Alf P. Steinbach" <al...@start.no> wrote:
> * kmw:
>
> > Hello,
>
> > I am working on container class with different implementations and
> > want to add stl-style iterators.
>
> It may be easiest to write a templated wrapper that uses some underlying
> conventional named methods interface to provide STL iterator functionality.
>
>
>
> > Now, I am confronted with a
> > "conversion to non-scalar type" error which I do not understand. Any
> > comments are appreciated. Many thanks in advance!
>
> > The interface for the different implementations is defined in the base
> > class A. A1 is one implementation. B is the iterator base class and C
> > its implementation in A1. I really do not see a problem since C
> > inherits from B but the compiler says:
>

> > test.cpp: In function ‘int main()’:
> > test.cpp:34: error: conversion from ‘A<int>::B’ to non-scalar type

> > ‘A1<int>::C’ requested

James Kanze

unread,
Oct 29, 2009, 12:48:57 PM10/29/09
to
On Oct 29, 3:20 pm, kmw <wuerz...@gmail.com> wrote:

> I am working on container class with different implementations
> and want to add stl-style iterators. Now, I am confronted with
> a "conversion to non-scalar type" error which I do not
> understand. Any comments are appreciated. Many thanks in
> advance!

> The interface for the different implementations is defined in
> the base class A. A1 is one implementation. B is the iterator
> base class and C its implementation in A1. I really do not see
> a problem since C inherits from B but the compiler says:

> test.cpp: In function ‘int main()’:
> test.cpp:34: error: conversion from ‘A<int>::B’ to non-scalar type
> ‘A1<int>::C’ requested

> Code:

> return 0;
> }

You'll get the same problems without the iterators. The most
obvious problem (and why the compiler is complaining) is that
you're returning a A::B, and trying to use it to initialize an
A1::C; you can't normally use a base type to initialize a
derived type. The obvious solution for this is to use covariant
return types, except that covariant returns only work with
pointers and references, not with values.

Which brings us to the more general problem: Once A1::begin has
returned an A::B, all you have is an A::B---slicing has occured.
More generally, polymorphism only works through references or
pointers (and polymorphic classes should not generally be copied
or assigned). If you want the returned iterator to behave
polymorphically, you'll have to use some variant of the
letter/envelope or the handle idiom; for STL semantics, you'll
need deep copy, which will make copying iterators expensive.

--
James Kanze

0 new messages