1

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?

Community
  • 1
  • 1
SingerOfTheFall
  • 29,228
  • 8
  • 68
  • 105

3 Answers3

4

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;
}
Rost
  • 8,779
  • 28
  • 50
3
// 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
}
Luc Danton
  • 34,649
  • 6
  • 70
  • 114
3

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.

Cheers and hth. - Alf
  • 142,714
  • 15
  • 209
  • 331
  • If this is all in a header, it needs the `inline` keyword in front of the definition of `Base::toDerived` to avoid linker errors. – Mark Lakata May 21 '15 at 18:51
  • @MarkLakata: Well I would rather place the `inline` in front of the declaration in the class. Then it tells the reader that at definition follows later on in the header. That said, nothing indicated that this was a header, and in answers it's best to not add stuff that's not strictly necessary (it can easily be added when desired, but it's more difficult to decide that removing it is safe). – Cheers and hth. - Alf May 21 '15 at 22:22