conversion to non-scalar type error in inheritance hierarchy

Discussion in 'C++' started by kmw, Oct 29, 2009.

  1. kmw

    kmw Guest

    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;
    }
    kmw, Oct 29, 2009
    #1
    1. Advertising

  2. 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?

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


    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
    Victor Bazarov, Oct 29, 2009
    #2
    1. Advertising

  3. kmw

    kmw Guest

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

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

    >
    > 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, Oct 29, 2009
    #3
  4. * 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
    Alf P. Steinbach, Oct 29, 2009
    #4
  5. kmw

    kmw Guest

    > 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" <> 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

    >
    > > 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, Oct 29, 2009
    #5
  6. kmw

    James Kanze Guest

    On Oct 29, 3:20 pm, kmw <> 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:
    > 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'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
    James Kanze, Oct 29, 2009
    #6
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. venu reddy

    conversion to non-scalar type requested error

    venu reddy, Feb 19, 2007, in forum: C Programming
    Replies:
    2
    Views:
    16,927
    Barry Schwarz
    Mar 4, 2007
  2. Dhirendra Singh

    Conversion from scalar to class type

    Dhirendra Singh, May 11, 2006, in forum: C++
    Replies:
    6
    Views:
    469
    Jonathan Mcdougall
    May 13, 2006
  3. Replies:
    11
    Views:
    11,271
  4. Clint Olsen
    Replies:
    6
    Views:
    360
    Jeff 'japhy' Pinyan
    Nov 13, 2003
  5. Mark

    Replace scalar in another scalar

    Mark, Jan 27, 2005, in forum: Perl Misc
    Replies:
    4
    Views:
    163
    Arndt Jonasson
    Jan 27, 2005
Loading...

Share This Page