实现任何容器

时间:2013-07-19 03:09:34

标签: c++ templates boost-variant boost-any

我很清楚boost::anyboost::variant,但在这种情况下,它们不符合我的需求。

通常,要包含未知类型的对象,可以从公共库中派生它,并通过虚方法访问实例。但是,如果不可能使用共同基础,那会怎么做?

我知道在这个例子中你必须知道所包含的类型,但请耐心等待。 std::vector是一个模板类,顶级类也是模板。据我所知,如果不修改STL标头,就不能给出非模板库。现在,假设我想创建一个单一类型的向量,但包含类不关心类型,但它确实需要访问一些“常见”方法,size()和{{1}例如。

使用pop_back(),类型已被删除,几乎不可能取消引用所包含的对象。 boost::anyboost::variant需要事先知道可以插入哪些类型,从而导致包含类本身成为模板。

到目前为止我所拥有的是这样的:

tuple

此处客户端可以调用struct container { virtual ~container() = 0; virtual void pop_back() = 0; virtual size_t size() = 0; ... } template < typename T > struct contained { std::vector< T > _vec; contained ( size_t n, T _what ) : _vec( n, _what ) {} virtual void pop_back() { _vec.pop_back(); } ... } class some_class { container* _cont; template < typename T > void create ( T _first ) { _cont = new contained< T >(1,_first); } ... } ,并且应自动确定模板参数。我知道这不是一个很好的例子,但我试图隐藏客户端的模板参数。如果不这样做,create()也必须跟踪存储的类型。

我的方法依赖虚拟调用,这会导致性能下降,尤其是当内部类具有自己的虚拟方法时。

是否还有其他类型的容器可以更好地满足我的需求?

理想情况下,我喜欢这样的事情

some_class

在内部,它会跟踪类型并进行简单的转换而不是依赖虚拟方法。几乎像container = std::vector< T >; container.pop_back(); container.push_back( T2 ); // compile error if types don't match ,区别在于,一旦声明它的类型就可以改变。

编辑:

实际上,我想在auto周围创建一个包装器。此包装类根据BOM打开包含std::basic_filebufcharwchar_t的文件。包装器也派生自unsigned long,模板参数是客户选择的任何内容。在内部,它将unicode代码点从文件转换为客户端所需的编码。存储内部basic_filebuf时会出现问题,因为它可以使用任何类型声明为模板参数。我不想使用模板专业化,因为我希望客户端能够传入他们自己的basic_filebuf实例。

必须兼容VS2010,其功能与C ++ 11有限。

1 个答案:

答案 0 :(得分:0)

这不能与编译时类型检查结合使用。基于您的“理想”示例:

container c;
if (thingKnownAtRunTime()) {
  c = vector<int>;
} else {
  c = vector<string>;
}
c.push_back("hello world");

对于filebuf案例,你可能会得到类似的东西(警告:未经测试)

template<typename FILEBUF>
void gensputc(FILEBUF* fb, long long c) {
  FILEBUf::char_type c2 = smart_convert<FILEBUf::char_type>(c);
  fb->sputc(c2);
}

class FileBufWrapper {
public:
  template<typename FILEBUF> FileBufWrapper(FILEBUF* fb) {
    fb_ = fb;
    sputc_ = gensputc<FILEBUF>;
  }
  void sputc(long long c) {
    sputc_(fb_,c);
  }
private:
  typedef void(*sputc_t)(void*, long long);
  sputc_t sputc_;
  void* fb_;
};

如果无法将值转换为char类型,则smart_convert函数会抛出运行时异常。此外,还需要为您打算调用的每个函数执行此操作。

如果您可以访问c ++ 11的std :: function和std :: bind,那么这可以更加清晰,特别是对于您不需要转换任何内容的情况。