1

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

通常,为了包含一个未知类型的对象,人们会从一个公共基础派生它并通过虚拟方法访问该实例。但是,如果不可能使用一个共同的基地怎么办?

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

使用boost::any,类型已被删除,几乎不可能取消引用包含的对象。boost::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不同之处在于一旦声明它的类型可以改变。

编辑:

实际上,我想围绕std::basic_filebuf. 此包装类使用或char基于BOM 打开文件。包装器也派生自模板参数,无论客户选择什么。在内部,它将文件中的 unicode 代码点转换为客户端所需的编码。存储内部时会出现问题,因为它可以使用任何类型作为模板参数声明。我不想使用模板专业化,因为我希望客户端能够传入他们自己的实例。wchar_tunsigned longbasic_filebufbasic_filebufbasic_filebuf

必须与 VS2010 兼容,它具有 C++11 的有限功能。

4

1 回答 1

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,这可以变得更简洁一些,尤其是在您不需要转换任何内容的情况下。

于 2013-08-13T20:13:52.003 回答