2

This question relates very closely to Can a nested C++ class inherit its enclosing class?

My situation is complicated with templates which seemingly mean that the previous answer no longer works.

class Animal
{
    template <typename T>
    class Bear : public Animal
    {
        // …
    };

    template <typename T>
    class Giraffe : public Animal
    {
        // …
    };
};

// example usage

struct MyAnimal : Animal::Bear<Animal> { };

MyAnimal a;

Can something like this be made to work?

Community
  • 1
  • 1
paperjam
  • 8,321
  • 12
  • 53
  • 79
  • have you tried doing what they answer in the question you mentioned ? I don't see why using template will change anything. – mb14 Nov 01 '11 at 12:34

3 Answers3

3

The other answer works, you just need to know the syntax for it:

class Animal
{
    template <typename T>
    class Bear;

    template <typename T>
    class Giraffe;
};

template <typename T>
class Animal::Bear : public Animal
{
    ....
};

template <typename T>
class Animal::Giraffe : public Animal
{
    ....
};
tenfour
  • 36,141
  • 15
  • 83
  • 142
  • This does not work. My compiler (VS2010) complains that `Animal::Bear` is not defined. I am using it later as a base class in another templated class in CRTP style. `T` is `Animal`. – paperjam Nov 01 '11 at 12:44
  • Post a minimal example of the problem then. This is the solution to the question you asked. – tenfour Nov 01 '11 at 12:52
  • @paperjam: This solution compiles just fine in my gcc 4.6.1, and looks right to me. – thiton Nov 01 '11 at 13:07
  • Yes, my minimal example compiles with this solution. I guess I have more dependencies in my real code - am trying to find a way to replicate minimally... – paperjam Nov 01 '11 at 13:17
1

Sure it can. Like suggested in the original question just use forward declaration.

#include <iostream>

class Animal
{
public:
    template <typename T>
    class Bear;

    template <typename T>
    class Giraffe;

    int val;
};

template <typename T>
class Animal::Bear : public Animal
{
    public:
    T b_member;

    virtual void print(){
        std::cout << b_member.val << endl;
    }

};

template <typename T>
class Animal::Giraffe : public Animal
{
    public:
    T g_member;

    virtual void print(){
        std::cout << g_member.val << endl;
    }
};

struct BearAnimal : Animal::Bear<Animal> 
{ 
};

struct GiraffeAnimal : Animal::Giraffe <Animal> 
{ 
};


int main()
{
    BearAnimal btest;
    GiraffeAnimal gtest;
    btest.b_member.val = 1;
    gtest.g_member.val = 2;
    btest.print();
    gtest.print();    

    return 0;
}

Output:

1 2

enticedwanderer
  • 4,346
  • 28
  • 24
  • 1
    I think you have two different `Bear` classes and two `Giraffe` classes here. The ones that work aren't nested. – paperjam Nov 01 '11 at 12:48
0

You can't do that because inheriting requires the full class definition to be available. Since Bear and Giraffe's use within Animal could affect the definition of Animal you wind up almost with a circular dependency.

Instead, group the related classes in a namespace. I see no reasons why specific animals should be nested within Animal at all.

Mark B
  • 95,107
  • 10
  • 109
  • 188
  • My real code has no `Animals`. I'm using CRTP and it is very clean and convenient to have the templated derived class nested inside one of its base classes. – paperjam Nov 01 '11 at 13:18