将模板类强制转换为更一般的专门化 [英] Casting templated class to more general specialization

查看:178
本文介绍了将模板类强制转换为更一般的专门化的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个模板类,模板参数的类将保存的一些数据点的维数。这个类有一个专门的版本 MyClass< -1> ,允许在编译时不知道尺寸。

I have a templated class with the template argument the number of dimensions of some datapoints the class shall save. This class has a specialized version MyClass<-1> that allows for dimensions not known at compile time.

我可以将一个特定的类(比如 MyClass <2> )转换成这个更一般的形式?

How can I cast a specific class (say MyClass<2>) to this more general form?

比较具体,这里是一些人工的例子,显示情况。 (我使用Eigen库,但我想一般的原则,这不应该关系)

To be a bit more concrete, here is some artificial example that shows the situation. (I use the Eigen library, but I suppose for the general principle this should not matter)

using namespace Eigen;

template <std::size_t dim>
class MyClass {
  public:
    // Some constructors...

    // A sample function:
    Matrix<double, dim, 1> returnPoint();

    // Some more functions here

  private:
    Matrix<double, dim, 1> point;
}

现在,假设我有以下代码段:

Now, suppose I have the following code segment:

MyClass<2> *foo;
MyClass<Dynamic> *bar;  // Dynamic is a Eigen constant, being defined as -1

// Do something here

// How to do this:
bar = some_cast<MyClass<Dynamic> *>(foo);

考虑到这个问题,我想我想要的是不可能归档而不实际复制point的值。任何人能够证明我的错误或确认这个假设?

Thinking about the problem I suppose what I want is impossible to archive without actually copying the values of point. Anybody able to prove me wrong or confirm this assumption?

推荐答案

当你使用两组不同的参数来实例化一个类模板时,你会得到两个不同的类,不相关的。除非你明确定义一个继承自另一个,例如:

When you instantiate a class template with two different sets of arguments you get two distinct classes that are not related. Unless you specifically define one to inherit from the other, for example:

namespace with_inheritance {

template <class T, long sz>
class vector : public vector<T,-1> {
    typedef vector<T,-1> base_t;
public:
    vector() : base_t (sz) { }
};

template <class T>
class vector<T, -1> {
    T* v_;
    size_t sz_;
public:
    vector(size_t sz) : v_ (new T[sz]), sz_ (sz) { }
    ~vector() { delete [] v_; }
    T& operator[](size_t i)
    {
        if (i >= sz_) throw i;
        return v_[i];
    }
};

} // with_inheritance

在这种情况下, :

namespace wi = with_inheritance;
wi::vector<double, 10> v;
wi::vector<double, -1>* p = &v;
std::cout << (*p)[1] << '\n';

不允许在它们之间转换继承关系。但是,您可以使用reinterpret_cast来绕过类型系统。但是你已经非常小心,对象具有相同的布局和不变量,以确保一切都能正常工作。如:

Without the inheritance relationship casting between them will not be permitted. You can, however, use reinterpret_cast to get around the type system when you want to. But you have be very careful that the objects have identical layout and invariants to make sure everthing will work ok. As in:

namespace with_lots_of_care {

template <class T, long sz>
class vector {
    T* v_;
    size_t sz_;
public:
    vector() : v_ (new T[sz]), sz_ (sz) { }
    ~vector() { delete [] v_; }
    T& operator[](size_t i)
    {
        if (i >= sz_) throw i;
        return v_[i];
    }
};

template <class T>
class vector<T, -1> {
    T* v_;
    size_t sz_;
public:
    vector(size_t sz) : v_ (new T[sz]), sz_ (sz) { }
    ~vector() { delete [] v_; }
    T& operator[](size_t i)
    {
        if (i >= sz_) throw i;
        return v_[i];
    }
};

} // with_lots_of_care

然后投射:

namespace wc = with_lots_of_care;
wc::vector<double, 10> v;
wc::vector<double, -1>* p = reinterpret_cast<wc::vector<double, -1>*>(&v);
std::cout << (*p)[1] << '\n';

这篇关于将模板类强制转换为更一般的专门化的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆