Это частично связано с этот ТАК вопрос.
У меня есть два класса, оба они шаблонные, например:
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
объявление, потому что это приведет к точно такой же проблеме, только наоборот.
Есть ли способ сделать это?
// 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
}
Эта проблема не имеет ничего с шаблонами. Вы можете просто использовать предварительную декларацию 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;
}
Ты можешь сделать
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;
}
Как видите, это не имеет ничего общего с шаблонами.
Кроме того, этот дизайн просто не чувствует себя хорошо.