Есть вот такая реализация shared_ptr.
Далее, где-то в клиентском коде есть иерархия классов с родителем:
class Creature {
public:
virtual void eat(shared_ptr<Fruit> f) = 0;
};
Теперь, хочется иметь возможность сделать:
class Apple : public Fruit {
...
public:
void appleSpecificMethod();
};
...
shared_ptr<Apple> pApple = new Apple;
pApple->appleSpecificMethod();
someCreature->eat(pApple); // иметь возможность передавать shared_ptr<производный_от_Fruit_класс> в eat(shared_ptr<Fruit>)
Для этого я добавляю в shared_ptr шаблонный конструктор:
template<class T> template <class Y>
inline shared_ptr<T>::shared_ptr(const shared_ptr<Y> &y) {
attachStorage(y.getStoragePtr());
}
и
template<class T> template<class Y>
inline void shared_ptr<T>::attachStorage(shared_ptr_storage<Y> *pStorage) {
// Вопрос:
// Как правильно сделать проверку валидности преобразования Y* к T* во время компиляции?
// Ничего кроме этого в голову не приходит:
// {
// Y *pY = NULL;
// T *pT = pY;
// }
myStorage = reinterpret_cast<shared_ptr_storage<T>*>(pStorage);
if (myStorage != 0) {
myStorage->addReference();
}
}
Здравствуйте, kbjm, Вы писали:
K>Вопрос:
K>Как правильно сделать проверку валидности преобразования Y* к T* во время компиляции?
вариант 1 (с перегрузкой, т.е. "плохой" конструктор просто не будет найден)
template<class T> template<class Y>
inline
typename boost::enable_if< boost::is_convertible<X,Y> >::type
shared_ptr<T>::attachStorage(shared_ptr_storage<Y> *pStorage)
{
}
вариант 2 (с ошибкой компиляции)
template<class T> template<class Y>
inline void
shared_ptr<T>::attachStorage(shared_ptr_storage<Y> *pStorage)
{
BOOST_STATIC_ASSERT((boost::is_convertible<X,Y>::value));
// или (еще и типы распечатает)
BOOST_MPL_ASSERT_MSG((boost::is_convertible<X,Y>::value), NO_CONVERSION, (types<X,Y>));
}