是否可以以这样的方式实现类模板:如果一个对象的模板参数相关,则可以将一个对象转换为另一个对象?这是一个显示这个想法的exaple(当然它不会编译):
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&amp; S的函数的接口。和T *,所以我无法实现模板复制构造函数。
我正在编写一个通用的Iterator类,它可以容纳任何STL迭代器,除了类型擦除之外我还希望它是多态的,即我可以写这样的东西:
std::list<Derived> l;
MyIterator<Base> it(l.begin());
UPD:这是我的错误,我实际上并不需要将Foo *转换为Foo *来实现MyIterator,所以我认为这个问题已经不再存在了。
答案 0 :(得分: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
!
好的,既然您提供了更多信息,很明显您想要做一些完全不同的事情。这是一些启动者:
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
。运气好的话,您可以将该模板用于您的目的(我还没有测试过)。
答案 1 :(得分:4)
虽然其他答案指出这种关系并非“内置”模板,但您应该注意,可以构建功能来处理这种关系。例如,boost::shared_dynamic_cast
and friends给出
class A { ... };
class B : public A { ... };
让您在boost::shared_ptr<A>
和boost::shared_ptr<B>
之间进行投射。
请注意,如果你真的要实现这样的东西,你必须要小心MyIterator支持的操作。例如,使用MyIterator<Base>(std::list<Derived>::iterator)
的示例,您不应该有operator*()
的左值版本,例如,
*myIter = someBaseValue;
不应该编译。
答案 2 :(得分:1)
Foo<Derived>
不会继承Foo<Base>
,因此您无法将前者转换为后者。此外,您的假设是错误的:dynamic_cast
将失败。
您可以创建一个Foo<Base>
实例的新对象来复制您的Foo<Derived>
实例,但我想这就是您正在寻找的内容。