Как быть с классами, которые зависят друг от друга и имеют члены-шаблоны?

Это частично связано с этим вопросом SO.

У меня есть два класса, оба они шаблонные, например:

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

Как видите, оба шаблонны, и внутри функции класса Base мне нужно создать экземпляр Derived. Конечно, так, как сейчас, я получаю ошибку Derived does not name a type. К сожалению, я не могу просто объявить Derived, потому что это приведет к другой ошибке variable 'Derived d ' has initializer but incomplete type.

Из вопроса SO, который я упомянул выше, я понимаю, что компилятору необходимо знать обо всех параметрах шаблона, чтобы иметь возможность правильно объявить его. Но, очевидно, я не могу просто переместить объявление Derived вверх, потому что это приведет к точно такой же проблеме, только наоборот.

Есть ли способ сделать это?


person SingerOfTheFall    schedule 28.09.2012    source источник
comment
Это как-то связано с шаблонами?   -  person juanchopanza    schedule 28.09.2012
comment
Я бы сказал, что Derived должен иметь fromBase.   -  person GManNickG    schedule 28.09.2012
comment
а. вам не хватает ; после определений классов. б. Я согласен с GManNickG - то, что вы сделали, не является хорошим ООП.   -  person elyashiv    schedule 28.09.2012
comment
@elyashiv, спасибо, я случайно удалил их при создании примера;)   -  person SingerOfTheFall    schedule 28.09.2012
comment
@GManNickG, это хороший момент, я подумаю об этом ;) Но в любом случае я хотел бы знать, возможно ли это, как я выразился, даже с целью узнать, возможно ли это в принципе ...   -  person SingerOfTheFall    schedule 28.09.2012


Ответы (3)


Эта проблема не имеет ничего общего с шаблонами. Вы можете просто использовать предварительное объявление Derived для компиляции объявления Base::toDerived() и переместить определение функции в зависимости от Derived после определения Derived:

// 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;
}
person Rost    schedule 28.09.2012

Ты можешь сделать

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

Как видите, это не имеет ничего общего с шаблонами.

Кроме того, этот дизайн просто не кажется правильным.

person Cheers and hth. - Alf    schedule 28.09.2012
comment
Если все это находится в заголовке, ему нужно ключевое слово inline перед определением Base::toDerived, чтобы избежать ошибок компоновщика. - person Mark Lakata; 21.05.2015
comment
@MarkLakata: Ну, я бы предпочел поставить inline перед объявлением в классе. Затем он сообщает читателю, что определение at следует позже в заголовке. Тем не менее, ничто не указывало на то, что это был заголовок, и в ответах лучше не добавлять вещи, которые не являются строго необходимыми (их можно легко добавить при желании, но сложнее решить, что их удаление безопасно). - person Cheers and hth. - Alf; 22.05.2015

person    schedule
comment
Спасибо ;) Это так просто, что мне даже стыдно xD - person SingerOfTheFall; 28.09.2012
comment
Если все это находится в заголовке, ему нужно ключевое слово inline перед определением Base::toDerived, чтобы избежать ошибок компоновщика. - person Mark Lakata; 21.05.2015