Inheritance and friendship

Discussion in 'C++' started by Edoardo Tagome, Aug 8, 2013.

  1. Hi,
    first of all I must apologize if I'm OT (and I fear I may be) but I
    couldn't find a better NG (at least among the ones I have access to).

    I can build this code in Visual Studio 2010 but g++ (android-ndk-r8d)
    fails to build.

    As you can see the problem has to do woth friendship and inheritance

    B<T>
    ^
    |
    |
    F<T>
    ^
    |
    |
    A


    ---- MaGoTest.hpp BEGIN ----

    template <class T>
    class MaGoTestB
    {

    private:
    T *mVar ;

    public:
    void M2( void ) ;

    } ;


    template <class T>
    class MaGoTestF : public MaGoTestB< T >
    {

    private:
    T *mVar ;

    public:
    void M3( void ) ;

    } ;


    class MaGoTestA : public MaGoTestF< MaGoTestA >
    {
    template <class U> friend class MaGoTestB;
    //template <class U> friend class MaGoTestF;

    private:

    public:
    void M1( void ) ;

    } ;

    ---- MaGoTest.hpp END ----


    ---- MaGoTest.cpp BEGIN ----

    #include "MaGoTest.hpp"

    void MaGoTestA::M1( void )
    {
    return ;
    }

    template< class T >
    void MaGoTestB< T >::M2( void )
    {
    return ;
    }

    template< class T >
    void MaGoTestF< T >::M3( void )
    {
    return ;
    }

    ---- MaGoTest.hpp END ----

    The error is:

    In file included from
    C:/Users/edotgm/Desktop/SRC/MaGo_Sample/SRC/MaGoTest.cpp:1:0:
    C:/Users/edotgm/Desktop/SRC/MaGo_Sample/SRC/MaGoTest.hpp:29:41: error:
    specialization of 'MaGoTestB<MaGoTestA>' after instantiation
    make: *** [obj/local/armeabi/objs-debug/MaGoMmon/MaGoTest.o] Error 1


    It's not clear to me if this is a c++ problem, an unsupported feature of
    g++ or if I have to enable something through command line switches in g++ .

    Hope there is someone in this NG who can enlighten me abiut this issue :)

    Thanks
     
    Edoardo Tagome, Aug 8, 2013
    #1
    1. Advertising

  2. On 8/8/2013 9:02 AM, Edoardo Tagome wrote:
    > Hi,
    > first of all I must apologize if I'm OT (and I fear I may be) but I
    > couldn't find a better NG (at least among the ones I have access to).
    >
    > I can build this code in Visual Studio 2010 but g++ (android-ndk-r8d)
    > fails to build.
    >
    > As you can see the problem has to do woth friendship and inheritance
    >
    > B<T>
    > ^
    > |
    > |
    > F<T>
    > ^
    > |
    > |
    > A
    >
    >
    > ---- MaGoTest.hpp BEGIN ----
    >
    > template <class T>
    > class MaGoTestB
    > {
    >
    > private:
    > T *mVar ;
    >
    > public:
    > void M2( void ) ;
    >
    > } ;
    >
    >
    > template <class T>
    > class MaGoTestF : public MaGoTestB< T >
    > {
    >
    > private:
    > T *mVar ;
    >
    > public:
    > void M3( void ) ;
    >
    > } ;
    >
    >
    > class MaGoTestA : public MaGoTestF< MaGoTestA >
    > {
    > template <class U> friend class MaGoTestB;
    > //template <class U> friend class MaGoTestF;
    >
    > private:
    >
    > public:
    > void M1( void ) ;
    >
    > } ;
    >
    > ---- MaGoTest.hpp END ----
    >
    >
    > ---- MaGoTest.cpp BEGIN ----
    >
    > #include "MaGoTest.hpp"
    >
    > void MaGoTestA::M1( void )
    > {
    > return ;
    > }
    >
    > template< class T >
    > void MaGoTestB< T >::M2( void )
    > {
    > return ;
    > }
    >
    > template< class T >
    > void MaGoTestF< T >::M3( void )
    > {
    > return ;
    > }
    >
    > ---- MaGoTest.hpp END ----
    >
    > The error is:
    >
    > In file included from
    > C:/Users/edotgm/Desktop/SRC/MaGo_Sample/SRC/MaGoTest.cpp:1:0:
    > C:/Users/edotgm/Desktop/SRC/MaGo_Sample/SRC/MaGoTest.hpp:29:41: error:
    > specialization of 'MaGoTestB<MaGoTestA>' after instantiation
    > make: *** [obj/local/armeabi/objs-debug/MaGoMmon/MaGoTest.o] Error 1
    >
    >
    > It's not clear to me if this is a c++ problem, an unsupported feature of
    > g++ or if I have to enable something through command line switches in g++ .
    >
    > Hope there is someone in this NG who can enlighten me abiut this issue :)


    First, your posting is *not* off-topic. It's perfectly OK, IMNSHO.

    Second, I would like to make a couple of suggestions. While using mixed
    case might look good and readable to you, when the names of two
    templates only differ in one letter out of nine, that's difficult to
    read to some of us. For the sake of posting here, naming your templates
    'Base' and 'Der' would work just as nicely, and be more readable. Also,
    what is the point of making unrelated template instantiation (actually,
    all of them) a friend of your '...A' class? Your class has no private
    members, and no instantiation attempts to access them. Also, put the
    instantiations of the template's members into the header in order to
    avoid unpleasant errors. Also, get rid of the 'void' between the
    parentheses. If the parentheses are intended to be empty, they ought to
    be *empty*.

    IOW, your code I would rather see as

    ---- MaGoTest.hpp BEGIN ----
    template <class T> class Base
    {
    T *mVar; // it's private, no need to say it
    public:
    void M2() {}
    };

    template <class T> class Der : public Base<T>
    {
    T *mVar ;
    public:
    void M3() {}
    };

    class A : public Der<A>
    {
    template <class U> friend class Base;
    public:
    void M1() {}
    };
    ---- MaGoTest.hpp END ----

    ....although I don't really see the point in defining all those member
    functions or the friendship between A and Base<U>. Try to put the
    implementation of Base<T>::M2 and Der<T>::M3 in the class template
    definition itself. You will find it necessary anyway when the linker
    complains (even if you get the 'friend' declaration to compile or just
    remove it).

    In the future, consider that it's quite useful to let us know what
    problem you're trying to solve. Perhaps the friendship between a class
    derived from a derived class of some base template instantiation and all
    instances of that grandfather class template is not really a good
    solution for what you're trying to accomplish...

    Good luck!

    V
    --
    I do not respond to top-posted replies, please don't ask
     
    Victor Bazarov, Aug 8, 2013
    #2
    1. Advertising

  3. On 08/08/2013 16:01, Victor Bazarov wrote:

    >
    > First, your posting is *not* off-topic. It's perfectly OK, IMNSHO.
    >
    > Second, I would like to make a couple of suggestions. While using mixed


    Thanks Victor for your reply: I've tried to follow your hints and came
    up with a more complete example.
    I've discovered that this builds both under Visual Studio 2010 and
    Debian Squeeze gcc, but not under Android (gcc port?) ndk-r8d .
    The reason I want this to build is because I'm porting to Android code
    that makes heavy use of such formulations and I'd like not to change it
    if possible.
    I'd like to know what causes this compiler behaviour and if there is a
    way to solve this issue without changing the code; i.e. using (for
    example) compiler command line switches.


    ---- MaGoTest.hpp BEGIN ----

    template <class T>
    class Base
    {

    public:
    static void Build()
    {
    new T() ;
    }

    } ;


    template <class T>
    class Der : public Base< T >
    {

    public:
    static void Build()
    {
    Base<T>::Build() ;
    }

    } ;


    class A : public Der< A >
    {
    template <class T> friend class Base ;
    template <class T> friend class Der ;

    private:
    A() ;

    } ;

    ---- MaGoTest.hpp END ----

    ---- MaGoTest.cpp BEGIN ----

    #include "MaGoTest.hpp"
    #include <iostream>

    A::A()
    {
    std::cout << "A constructor" << std::endl ;
    }

    ---- MaGoTest.cpp END ----

    ---- main.cpp BEGIN ----

    #include "MaGoTest.hpp"

    int main( void )
    {
    A::Build() ;

    return 0 ;
    }

    ---- main.cpp END ----


    Thanks
     
    Edoardo Tagome, Aug 8, 2013
    #3
  4. On 8/8/2013 1:07 PM, Edoardo Tagome wrote:
    > [..]
    > I've discovered that this builds both under Visual Studio 2010 and
    > Debian Squeeze gcc, but not under Android (gcc port?) ndk-r8d .
    > The reason I want this to build is because I'm porting to Android code
    > that makes heavy use of such formulations and I'd like not to change it
    > if possible.
    > I'd like to know what causes this compiler behaviour and if there is a
    > way to solve this issue without changing the code; i.e. using (for
    > example) compiler command line switches.


    You got me there. I don't know what causes this behaviour, but the
    usual reasons are a bug in the compiler or incomplete implementation of
    the Standard features by that particular compiler. More details about
    your specific compiler you will need to find in the documentation for
    the tool or in a forum that deals with that tool. I would hazard a
    guess that an Android compiler does indeed have a forum, although I am
    not aware of its precise location, so I'd start looking at the same web
    page where the Android developers hang out.

    The code, as you have already found out, is valid and *should* compile
    without a problem.

    V
    --
    I do not respond to top-posted replies, please don't ask
     
    Victor Bazarov, Aug 8, 2013
    #4
  5. On 09/08/2013 01:06, Sam wrote:
    >
    > This bug appears to be rather subtle.
    >
    > Inside the scope of class A, 'Base' appears to resolve to the
    > instantiated Base template in the superclass.
    >
    > Change this to:
    >
    > template <class T> friend class ::Base ;
    > template <class T> friend class ::Der ;
    >
    > And this should compile.
    >
    > Dunno which compiler is wrong, here. Too esoteric for my taste.
    >
    >



    Wow, thanks Sam for confirming the problem, finding the cause and
    suggesting a solution: even if I have to modify the code, I think I can
    apply such an easy change.

    Thank even to Victor :)
     
    Edoardo Tagome, Aug 21, 2013
    #5
    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. Marcin Vorbrodt

    Friendship inheritance

    Marcin Vorbrodt, Sep 3, 2003, in forum: C++
    Replies:
    4
    Views:
    1,639
    Big Brian
    Sep 4, 2003
  2. Thomas Matthews

    Circular Class Template Friendship

    Thomas Matthews, Jul 24, 2004, in forum: C++
    Replies:
    7
    Views:
    529
    Victor Bazarov
    Jul 28, 2004
  3. jimmy

    friendship and pImpl idiom

    jimmy, Feb 8, 2006, in forum: C++
    Replies:
    3
    Views:
    458
    Alf P. Steinbach
    Feb 9, 2006
  4. Replies:
    3
    Views:
    362
  5. Juha Nieminen

    Friendship and nested classes

    Juha Nieminen, Jun 13, 2008, in forum: C++
    Replies:
    2
    Views:
    351
    Martin York
    Jun 13, 2008
Loading...

Share This Page