异构容器仅使用静态多态性

jms*_*jms 6 c++ containers templates metaprogramming c++11

我的目标是实现一个容器(这里是一组堆栈,每种类型一个),同时接受许多不同类型的对象.在运行时,使用void指针(或所有存储类型的公共基类)和运行时类型识别(RTTI),这将是微不足道的.由于容器将要保存的所有类型在编译时都是已知的,因此可能(或可能不)使用模板来创建这样的类.我知道boost::variant已经提供了类似的功能,但它要求存储的类型作为模板参数列出,如boost::variant< int, std::string > v;.

我真正想要的是一个类,每次push()创建等效的新模板特化时,它都会向自己透明地添加匹配(内部)数据结构.该类的用法如下所示:

int main()
{
    MultiTypeStack foo;
    //add a double to the container (in this case, a stack). The class would
    //..create a matching std::stack<double>, and push the value to the top.
    foo.push<double>(0.1);
    //add an int to the container. In this case, the argument type is deduced.
    //..The class would create a std::stack<int>, and push the value to the top.
    foo.push(123);
    //push a second double to the internal std::stack<double>.
    foo.push<double>(3.14159);
    std::cout << "int: " << foo.top<int>() << "\n";      //"int: 123"
    std::cout << "double: " << foo.top<double>() << "\n";//"double: 3.14159"
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

以天真的实现为例:

template<typename T> struct TypeIndex;
template<> struct TypeIndex<int>{enum{i = 0};};
template<> struct TypeIndex<double>{enum{i = 1};};

class MultiTypeStack
{
public:
    template<typename T>
    void push(const T &val){std::get<TypeIndex<T>::i>(stacks_).push(val);}

    template<typename T>
    void pop(){std::get<TypeIndex<T>::i>(stacks_).pop();}

    template<typename T>
    T top(){return std::get<TypeIndex<T>::i>(stacks_).top();}
private:
    std::tuple<std::stack<int>, std::stack<double>> stacks_;
};
Run Code Online (Sandbox Code Playgroud)

Yak*_*ont 3

创建一个std::unordered_map<std::type_index, std::unique_ptr<unknown>>. 您键入的访问代码将采用该类型并找到适当的条目。然后static_castunknown一个依赖于保存你的堆栈的类型T

确保unknown是 的基数stack_holder<T>,并且unknown具有virtual析构函数。

这可能不完全是您想要的,但 C++ 类型系统是纯粹的:后面的表达式无法更改“较早”的类型。

如果链接类型,则可以构造更复杂的类型,但这只是在隐藏类型的同时列出类型。

如果对象是单例,则使用static局部变量的一些黑客行为可能会起作用。