SingerOfTheFall
SingerOfTheFall

Reputation: 29966

How to deal with classes that depend on each other and have template members?

This is partly related to this SO question.

I have two classes, both of them are templated, e.g.:

class Base
{
public:
    template< class T > void operator=(T other)
    {
        //irrelevant
    }

    Derived toDerived()
    {
        Derived d;
        //do stuff;
        return d;
    }
};

class Derived: public Base
{
public:
    template< class T > void foo( T other )
    {
        //do stuff 
    }
};

As you can see, both are templated, and inside of the Base class function I need to create an instance of Derived. Of course, the way it is now I'm getting an error Derived does not name a type. Unfortunately though, I can't just forward-declare Derived, because it will lead to another error variable 'Derived d ' has initializer but incomplete type.

From the SO question I mentioned above I understand that the compiler needs to know about all the template parameters to be able to forward-declare it correctly. But obviousle I can't just move Derived declaration up, because it will lead to exactly same problem, just vice-versa.

Is there a way to accomplish this?

Upvotes: 1

Views: 728

Answers (3)

Cheers and hth. - Alf
Cheers and hth. - Alf

Reputation: 145349

You can do

class Derived;

class Base
{
public:
    template< class T > void operator=(T other)
    {
        //irrelevant
    }

    Derived toDerived();
};

class Derived: public Base
{
public:
    template< class T > void foo( T other )
    {
        //do stuff 
    }
};

Derived Base::toDerived()
{
    Derived d;
    //do stuff;
    return d;
}

As you can see it has nothing to do with templates.

Also, this design simply doesn't feel right.

Upvotes: 3

Rost
Rost

Reputation: 9089

This problem has nothing with templates. You could just use forward declaration of Derived to compile declaration of Base::toDerived() and move the function definition depending on Derived after Derived definition:

// Forward declaration of Derived
class Derived;

// Definition of Base
class Base
{
public:
   // Base::toDerived() declaration only
   Derived toDerived();
};

// Definition of Derived
class Derived: public Base
{
public:
...
};

// Base::toDerived() definition
inline Derived Base::toDerived()
{
   Derived d;
   // Do dirty things
   return d;
}

Upvotes: 4

Luc Danton
Luc Danton

Reputation: 35449

// Declare, but do not define
class Derived;

class Base {
public:    
    // Declare, but do not define
    // at this point Derived must be declared to be able
    // to use it in the return type
    Derived toDerived();
};

// Define
class Derived: public Base {
    // Rest of definition
};

// At this point Derived is defined

// Define
Derived Base::toDerived()
{
    // Implementation goes here
}

Upvotes: 3

Related Questions