c++ - 将模板化类转换为更通用的特化

标签 c++ templates casting

我有一个模板化类,其模板参数是该类应保存的某些数据点的维数。这个类有一个专门的版本MyClass<-1>允许在编译时未知的维度。

如何将特定类(比如 MyClass<2>)转换为这种更通用的形式?

为了更具体一点,这里有一些人为的例子来说明这种情况。 (我使用 Eigen 库,但我想对于一般原则来说这应该无关紧要)

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;
}

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

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 的值,我想要的是不可能存档的。任何人都可以证明我错了或证实这个假设?

最佳答案

可以在不实际复制值的情况下实现转换,但前提是您小心翼翼地使其工作。

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

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 绕过类型系统。但是您必须非常小心,确保对象具有相同的布局和不变量,以确保一切正常。如:

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';

关于c++ - 将模板化类转换为更通用的特化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13684521/

相关文章:

c++ - 如果没有头文件,.lib 文件是否无用?

c++ - 与 C++ 中的模板类混淆

templates - 如何使用 meteor 模板创建类似目录的结构?

Android - CaptioningManager 类

c++ - 删除空指针是否安全?

c++ - g++ : Using singleton in an embedded application

C++ 运行时错误

c++ - 实现 std::error_category,与自定义命名空间一起使用时的名称解析问题

c++ - 在没有参数列表的情况下无效使用模板名称

c# - 如何将 C# 对象拆箱为动态类型