1

テンプレート引数を持つテンプレート化されたクラスがあり、クラスが保存するいくつかのデータポイントの次元数があります。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);

問題について考えてみると、ポイントの値を実際にコピーしないと、私が望むものをアーカイブすることは不可能だと思います。私が間違っていることを証明したり、この仮定を確認したりできる人はいますか?

4

1 に答える 1

0

値を実際にコピーせずにキャストを実行することは可能ですが、注意して機能させた場合に限ります。

2 つの異なる引数セットを使用してクラス テンプレートをインスタンス化すると、関連していない 2 つの異なるクラスが得られます。一方を他方から継承するように明確に定義しない限り、たとえば次のようになります。

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';
于 2012-12-05T05:47:10.990 に答える