如何在C ++中实现模板类协方差? [英] How to implement template class covariance in C++?

查看:110
本文介绍了如何在C ++中实现模板类协方差?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

有可能实现一个类模板,这样一个对象可以转换到另一个如果他们的模板参数相关?这里是一个exaple来显示的想法(当然不会编译):

Is it possible to implement a class template in such a way that one object could be casted to another if their template arguments are related? Here is an exaple to show the idea (of course it will not compile):

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 *,所以我不能实现一个模板复制构造函数。

The additional problem here is that Foo is an abstract class used as an interface containing functions returning T& and T*, so I can't implement a template copy constructor.

我写一个通用的Iterator类,可以容纳任何STL迭代器,除了类型擦除我希望它是多态的,即我可以这样写:

I'm writing a universal Iterator class which can hold any STL iterator, and in addition to type erasure I'd like it to be polymorphic, i.e. I could write something like this:

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

UPD:这是我的错误,我实际上不需要Foo * MyIterator,所以我认为这个问题不再是真的。

UPD: That was my mistake, I didn't actually need casting Foo* to Foo* to implement MyIterator, so I think the question is not actual anymore.

推荐答案

模板参数与对象的内容无关你指向。没有理由这应该工作。说明

The template argument has nothing to do with the content of the object you are pointing to. There is no reason this should work. To illustrate

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 '

You will eventually access integer bar that doesn't really exist in a!

你提供了一些更多的信息,很明显你想做一些完全不同的事情。这是一些起始者:

OK, now that you provided some more information, it's clear you want to do something completely different. Here is some starter:

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 。有一点运气,你可以使用该模板为您的目的(我没有测试它)。

You may want to look into any_iterator. With a bit of luck, you can use that template for your purpose (I haven't tested it).

这篇关于如何在C ++中实现模板类协方差?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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