Приведение типов шаблонов C ++ с производными - PullRequest
5 голосов
/ 01 октября 2009

Я пытаюсь привести из одного дженерика к другому, сказать:

myClass<MoreAbstract> anItem = myclass<DerivateFromMoreAbstract> anotherObject;

Или сделать что-то вроде

aFunction(anotherObject); // myclass<DerivateFromMoreAbstract> anotherObject 

где aFunction подпись

aFunction(myClass<MoreAbstract> item);

Фактически, myClass - это упрощенная реализация shared_ptr, которую я нашел в Интернете. Мне интересно, есть ли какой-нибудь способ, которым я могу на самом деле переключаться с одного типа указателя на другой, будучи инкапсулированным.

Есть ли способ сделать такое кастинг? Если да, то как правильно это сделать?

Если это кому-нибудь поможет, VC ++ выдаст мне эту ошибку:

Error 1 error C2440: 'type cast' : cannot convert from 'myClass<T>' to 'myClass<T>'

Ответы [ 4 ]

11 голосов
/ 01 октября 2009

Вы не можете использовать статическое приведение, поскольку они несовместимы. Иногда вы можете создать оператор для приведения типа вместо

#include <iostream>

class A { };

class B : public A { };


template<typename T>
struct holder {
    T* value;

    holder ( T*value ) : value ( value ) { }

    template < typename U > // class T : public U
    operator holder<U> () const
    {
        return holder<U>( value );
    }
};


int main ()
{
    using namespace std;

    B   b;

    holder<B>   hb ( &b );
    holder<A>   ha  = hb;

    cout << boolalpha;

    cout << ( hb.value == ha.value ) << endl;

    return 0;
}

Является ли это значимой операцией, скорее зависит от семантики класса шаблона - если aFunction может поместить что-либо в обработчик, вы не хотите, чтобы более конкретный объект был мутирован. Следовательно, вы как-то копируете, либо с помощью оператора приведения, либо с помощью конструктора копирования шаблона и присваивания. (приведение меньше кода, но может привести к созданию большего количества объектов, если вы не используете ссылочные параметры)

6 голосов
/ 01 октября 2009

Типы не являются конвертируемыми по умолчанию таким образом (потому что вы, возможно, не хотите, чтобы объекты делали это). В общем, вы можете использовать два подхода:

Реализация явной функции приведения, которая может быть полезна для приведения во время выполнения, например boost's shared_ptr dynamic_pointer_cast . Вы бы получили что-то вроде:

template <typename To, typename From>
myclass<To> myclass_cast(const myclass<From>&)
{ /* do a runtime cast, possibly with exceptions */ }

Второй метод - это конвертирующий конструктор, который хорош, если его можно решить во время компиляции, если они конвертируемы. Например, если все классы можно преобразовать из шаблонного в Derived в шаблонный в Base, вот конструктор, который будет работать только тогда, когда это правда (используя enable_if и boost :: type_traits):

template <typename To>
class myclass {
  //converting constructor
  template <typename From>
  myclass(const myclass<From>&,
          typename enable_if<boost::type_traits::is_base_of<To, From> >::type* dummy = 0)
  {  }
};
3 голосов
/ 01 октября 2009

Извините, это невозможно. (Ну, если вы не делаете мерзких reinterpret_cast взломов, но вы не хотите этого делать - конечный результат не будет красивым).

T<Base> и T<Derived> не связаны. Компилятор не может этого допустить - помните, что вполне возможно, что T был специализирован для Derived как нечто совершенно иное.

1 голос
/ 01 октября 2009

Шаблоны в c ++, а также шаблоны в c ++. Net не являются ковариантными.

Отметьте , этот вопрос может дать вам представление об обходном пути.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...