Перекрестные ссылки при использовании параметров шаблона

Я обычно знаю, как бороться с перекрестными ссылками, но здесь я застрял.

Пусть умный указатель класса:

template< typename T >
SharedPointer
{
T * _ptr;
};

А также :

class Array;

class Value
{
SharedPointer< Array > _pa;
};

А также :

class Array
{
Value someFunc();
}

Здесь у меня есть предупреждения в классе SharedPointer о том, что я удаляю указатели на объекты неполного типа, что, я думаю, связано с предварительным объявлением.

Warning 2   warning C4150: deletion of pointer to incomplete type 'script::Array'; no destructor called c:\XXXXX\SharedPointer.h    77

Что я мог сделать, чтобы решить это? Единственное решение, которое я вижу, это переписать весь класс SharedPointer в нечто вроде:

template< typename pT >
SharedPointer
{
pT _ptr;
};

И используйте это так вместо этого:

SharedPointer< Array * >

Я хотел бы избежать переписывания этого класса, если это возможно. Есть ли другое решение?
Спасибо 🙂

РЕДАКТИРОВАТЬ: Вот реальный исходный код:

class Value
{
PUBLIC enum type_e
{
E_NULL,

E_INT,

E_FLOAT,

E_STRING,

E_ARRAY,

E_MAP,

E_FUNCTION,

E_REFERENCE // TODO For functions like fn( scalar & val )
};

PRIVATE union
{
int _i;

float _f;

std::string * _ps;

IFunction * _pf;
};

PRIVATE SharedPointer< Array > _pa;

PRIVATE SharedPointer< Map > _pm;

PRIVATE SharedPointer< Value > _ref;

PRIVATE type_e _type;

PUBLIC Value();

PUBLIC Value( bool b );

PUBLIC Value( int i );

PUBLIC Value( float f );

PUBLIC Value( const std::string & s );

PUBLIC Value( SharedPointer< Array > pa );

PUBLIC Value( SharedPointer< Map > pm );

PUBLIC Value( IFunction * pf );

PUBLIC Value( SharedPointer< Value > ref );

PUBLIC Value( const Value & v );

PUBLIC ~Value() { }

PUBLIC Value operator + ( const Value & v ) const;

PUBLIC Value operator - ( const Value & v ) const;

PUBLIC Value operator * ( const Value & v ) const;

PUBLIC Value operator / ( const Value & v ) const;

PUBLIC Value operator % ( const Value & v ) const;

PUBLIC Value operator ^ ( const Value & v ) const;

PUBLIC Value operator << ( const Value & v ) const;

PUBLIC Value operator - () const;

PUBLIC Value operator && ( const Value & v ) const;

PUBLIC Value operator || ( const Value & v ) const;

PUBLIC Value xor( const Value & v ) const;

PUBLIC Value operator ! () const;

PUBLIC Value & operator = ( const Value & v );

PUBLIC Value operator () ( Scope & scope, const std::vector< Value > & args ) const;

PUBLIC Value & getRef( const Value & v ) const;

PUBLIC Value getCpy( const Value & v ) const;

PUBLIC inline type_e getType() const throw() { return _type; }

PUBLIC inline bool isNull() const throw() { return E_NULL == _type; }

PUBLIC inline bool isInt() const throw() { return E_INT == _type; }

PUBLIC inline bool isFloat() const throw() { return E_FLOAT == _type; }

PUBLIC inline bool isString() const throw() { return E_STRING == _type; }

PUBLIC inline bool isArray() const throw() { return E_ARRAY == _type; }

PUBLIC inline bool isMap() const throw() { return E_MAP == _type; }

PUBLIC inline bool isFunction() const throw() { return E_FUNCTION == _type; }

PUBLIC inline bool isReference() const throw() { return E_REFERENCE == _type; }

PUBLIC inline bool isNumeric() const throw() { return E_INT == _type || E_FLOAT == _type; }

PUBLIC type_e toNumeric( int & asInt, float & asFloat ) const;

PUBLIC std::string toString() const;

PUBLIC operator bool () const throw();
};

class Array
{
PRIVATE std::vector< Value > _items;

PUBLIC Array( const std::vector< Value > & items );

PUBLIC ~Array();

PUBLIC Value & getRef( int index );

PUBLIC Value getCpy( int index ) const;

PUBLIC int getSize() const;
};template< typename T >
class SharedPointer
{
template< typename U >
friend class SharedPointer;

PRIVATE T * p;

PRIVATE size_t * c;

PUBLIC SharedPointer()
: p()
, c() { }

PUBLIC explicit SharedPointer( T * s )
: p( s )
, c( new size_t( 1 ) ) { }

PUBLIC SharedPointer( const SharedPointer & s )
: p( s.p )
, c( s.c )
{
if( this->c )
{
++*(this->c);
}
}

PUBLIC SharedPointer & operator = ( const SharedPointer & s )
{
if( this != & s )
{
this->clear();

this->p = s.p;
this->c = s.c;

if( this->c )
{
++*(this->c);
}
}
return *this;
}

PUBLIC template< typename U >
SharedPointer( const SharedPointer< U > & s )
: p( s.p )
, c( s.c )
{
if( c )
{
++*(this->c);
}
}

PUBLIC ~SharedPointer()
{
this->clear();
}

PUBLIC void clear()
{
if( this->c )
{
if( *(this->c) == 1 )
{
delete this->p;
}
if( ! --*(this->c) )
{
delete this->c;
}
}

this->c = NULL;
this->p = NULL;
}

PUBLIC T * get() const
{
return this->c ? this->p : NULL;
}

PUBLIC T * operator -> () const
{
return this->get();
}

PUBLIC T & operator * () const
{
return *(this->get());
}
};

0

Решение

Проблема в том, что с Value не имеет деструктора, деструктор по умолчанию создан для вас. Поскольку он в конечном итоге определяется как встроенный, в определении класса вы в конечном итоге удаляете неполный тип. Другими словами, это как если бы вы написали это в своем заголовочном файле:

class Value
{
SharedPointer< Array > _pa;
~Value() { //This will end up calling the destructor for `_pa`. To do that, if needs `Array` to be a completely defined type. }
};

Сделайте деструктор явным и переместите его в файл cpp. Обратите внимание, что вы можете использовать default ключевое слово для определений, встречающихся и вне класса.

2

Другие решения