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;
}
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
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
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
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
> 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