C++模板类型转换与派生

tom*_*mzx 5 c++ templates casting

我试图从一个泛型转换为另一个,说:

myClass<MoreAbstract> anItem = myclass<DerivateFromMoreAbstract> anotherObject;
Run Code Online (Sandbox Code Playgroud)

或者做类似的事情

aFunction(anotherObject); // myclass<DerivateFromMoreAbstract> anotherObject 
Run Code Online (Sandbox Code Playgroud)

其中aFunction签名是

aFunction(myClass<MoreAbstract> item);
Run Code Online (Sandbox Code Playgroud)

实际上,myClass实际上是我在网上找到的shared_ptr的简化实现.我想知道是否有任何方式我可以实际从一种指针类型切换到另一种被封装的指针类型.

有没有办法做这样的演员?如果是这样,那么正确的做法是什么?

如果它对任何人有帮助,VC++会给我这个错误:

Error 1 error C2440: 'type cast' : cannot convert from 'myClass<T>' to 'myClass<T>'
Run Code Online (Sandbox Code Playgroud)

Pet*_*ham 12

您不能进行静态转换,因为它们是不兼容的类型.您有时可以创建一个运算符来强制类型

#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;
}
Run Code Online (Sandbox Code Playgroud)

这是否是一个有意义的操作,而不是取决于模板类的语义 - 如果aFunction可以将任何东西放入处理程序中,您不希望更具体的对象被改变.因此,您可以使用强制运算符或模板复制构造函数和赋值以某种方式进行复制.(强制代码较少,但如果不使用引用参数,可能会导致创建更多对象)

  • 我更喜欢转换构造函数到转换运算符,因为后者无法启用或禁用 (2认同)

Tod*_*ner 6

类型不是以这种方式默认可转换的(因为您可能不希望对象这样做).一般来说,您可以采取两种方法:

实现一个显式的强制转换函数,它可能对运行时强制转换很有用,比如boost的shared_ptr dynamic_pointer_cast.你最终得到的结果如下:

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

第二种方法是转换构造函数,如果它们是可转换的,则在编译时它是可判定的.例如,如果所有类都可以从Derived上的模板转换为基于模板化,那么这是一个只有在为真时才能工作的构造函数(使用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)
  {  }
};
Run Code Online (Sandbox Code Playgroud)