实现任意容器
Implementing an any container
我很清楚boost::any
和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
的包装器。这个包装类基于BOM打开具有char
、wchar_t
或unsigned long
的文件。包装器也是从basic_filebuf
派生的,模板参数是客户端选择的任何参数。在内部,它将文件中的unicode代码点转换为客户端所需的编码。存储内部basic_filebuf
时会出现问题,因为它可以用任何类型声明为模板参数。我不想使用模板专用化,因为我希望客户端能够传入自己的basic_filebuf
实例。
必须与VS2010兼容,而VS2010具有来自C++11的有限功能。
这不能与编译时类型检查结合使用。基于您的"理想"示例:
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,这可以做得更干净一些,尤其是在不需要转换任何内容的情况下。
- 如果没有malloc,链表实现将失败
- 如何在c++中实现处理器调度模拟器
- 如何在c++中使用引用实现类似python的行为
- 实现无开销push_back的最佳方法是什么
- 使用简单类型列表实现的指数编译时间.为什么
- 如何在BST的这个简单递归实现中消除警告
- 实现一个在集合上迭代的模板函数
- 我应该实现右值推送功能吗?我应该使用std::move吗
- 如何正确实现和访问运算符的各种自定义枚举器
- C++Union/Struct位域的实现和可移植性
- 用常见虚拟函数实现的任意组合来实现派生类的正确方法是什么
- 如何在C++中实现节点数任意的通用树数据结构?
- 如何在C++中围绕任意值实现我所谓的"wraparound sort"?
- 实现任意精度的浮点库
- 如何高效实现任意序列的按位旋转?
- 实现任意容器
- 实现任意类型擦除的小缓冲区优化的简单方法(如std::function.)
- boost::multi_index_container:从任意索引中取equal_range,只实现一次循环
- 任意算术类型的比较:有人知道实现吗?
- 我可以知道一个多态对象是否实现了一个任意的抽象类