2

テンプレート引数が関連している場合、あるオブジェクトを別のオブジェクトにキャストできるような方法でクラス テンプレートを実装することは可能ですか? アイデアを示す例を次に示します (もちろん、コンパイルされません)。

struct Base {};
struct Derived : Base {};

template <typename T> class Foo {
    virtual ~Foo() {}
    virtual T* some_function() = 0;
};

Foo<Derived>* derived = ...;
Foo<Base>* base = derived;

ここでの追加の問題は、Foo が T& および T* を返す関数を含むインターフェイスとして使用される抽象クラスであるため、テンプレート コピー コンストラクターを実装できないことです。

私は任意の STL イテレータを保持できるユニバーサル Iterator クラスを作成しています。型消去に加えて、ポリモーフィックにしたいと考えています。つまり、次のように記述できます。

std::list<Derived> l;
MyIterator<Base> it(l.begin());

UPD:それは私の間違いでした。MyIterator を実装するために実際に Foo* を Foo* にキャストする必要はなかったので、この質問はもはや現実的ではないと思います。

4

3 に答える 3

4

他の回答では、この種の関係はテンプレートに「組み込まれていない」と指摘されていますが、この種の関係で機能する機能を構築できることに注意してください。たとえば、そして与えられboost::shared_dynamic_castた友人

class A { ... };
class B : public A { ... };

boost::shared_ptr<A>との間でキャストできますboost::shared_ptr<B>

このような実装を行う場合は、MyIteratorがサポートする操作に注意する必要があることに注意してください。たとえば、の例を使用するとMyIterator<Base>(std::list<Derived>::iterator)、の左辺値バージョンを使用しないでくださいoperator*()

  *myIter = someBaseValue;

コンパイルしないでください。

于 2011-02-05T18:49:39.663 に答える
4

テンプレート引数は、指しているオブジェクトの内容とは関係ありません。これが機能する理由はありません。説明する

struct Base { };
struct Derived : Base {};

template<typename T> struct A { int foo; };
template<> struct A<Base> { int foo; int bar; };

A<Derived> a;
A<Base> *b = &a; // assume this would work
b->bar = 0; // oops!

bar最終的には、実際には存在しない整数にアクセスしますa!


OK、さらに情報を提供したので、まったく別のことをしたいのは明らかです。ここにいくつかのスターターがあります:

template<typename T>
struct MyIterator : std::iterator<...> {
  MyIterator():ibase() { }
  template<typename U>
  MyIterator(U u):ibase(new Impl<U>(u)) { }
  MyIterator(MyIterator const& a):ibase(a.ibase->clone())

  MyIterator &operator=(MyIterator m) {
    m.ibase.swap(ibase);
    return *this;
  }

  MyIterator &operator++() { ibase->inc(); return *this; }
  MyIterator &operator--() { ibase->dec(); return *this; }
  T &operator*() { return ibase->deref(); }
  // ...

private:
  struct IBase { 
    virtual ~IBase() { }
    virtual T &deref() = 0; 
    virtual void inc() = 0;
    virtual void dec() = 0;
    // ...

    virtual IBase *clone() = 0;
  };
  template<typename U>
  struct Impl : IBase { 
    Impl(U u):u(u) { }
    virtual T &deref() { return *u; }
    virtual void inc() { ++u; }
    virtual void dec() { --u; }
    virtual IBase *clone() { return new Impl(*this); }
    U u;
  };

  boost::scoped_ptr<IBase> ibase;
};

その後、次のように使用できます

MyIterator<Base> it(l.begin());
++it; 
Base &b = *it;

を調べてみるとよいでしょうany_iterator。少し運が良ければ、そのテンプレートを目的に使用できます (私はテストしていません)。

于 2011-02-05T18:28:00.247 に答える
1

Foo<Derived>は を継承しないFoo<Base>ため、前者を後者に変換することはできません。また、あなたの仮定は間違っています:dynamic_cast失敗します。

Foo<Base>インスタンスをコピーするインスタンスの新しいオブジェクトを作成することもできますが、Foo<Derived>これがあなたが探しているものだと思います。

于 2011-02-05T18:28:53.970 に答える