在std :: vector中模板化存储多个不同类型

时间:2014-04-10 21:39:43

标签: c++ templates c++11 vector casting

谢谢大家的时间,我真的很感激。

需要使用模板化的方式在std :: vector中存储多个不同类型的变量。要使用以下函数,程序员必须知道它们存储变量的顺序以及存储的变量数。

class _NetVar {};

创建一个子类来保存实际变量:

template <class VARTYPE> class NetVar : public _NetVar
{
private:
    VARTYPE Var;
    NetVar(VARTYPE Value)
    {
        Var = Value;
    }
};

创建了基本辅助类

的向量
std::vector<_NetVar> DataVec;

将数据放入矢量中:

template <class DATATYPE> void AddData(DATATYPE AddData)
{
    DataVec.push_back(NetVar<DATATYPE>(AddData));
}

这里从数据中提取数据,内部变量保存向量的当前位置,并在每次请求变量时递增:

template <class DATATYPE> DATATYPE GetData()
{
    NetVar<DATATYPE> Temp = PacketData[VecPos];

    return Temp.Var;
    ++VecPos;
}

上一个函数是出现问题的地方,可以将子类识别为它的基类,但是可以将基类识别为它的一个子类吗?

以下是代码的使用方式:

AddData<int>(32);
AddData<bool>(true);
AddData<std::string>("Test");

auto Var1 = GetData<int>();
auto Var2 = GetData<bool>();
auto Var3 = GetData<std::string>();

当调用GetData时,抛出异常:

'initializing' : cannot convert from '_NetVar' to 'NetVar<DATATYPE>'

如果有人可以帮助我,我将不胜感激,再次感谢您的时间。

注意:需要避免使用Boost等外部库。

2 个答案:

答案 0 :(得分:3)

矢量应该是:

std::vector<_NetVar *> DataVec;

或高级指针

std::vector<std::shared_ptr<_NetVar> > DataVec;

这样您就可以将子类的实例而不是slicing存储到基类中。

在GetData上,您需要向上转换从向量中检索的指针。


编辑:添加完整的工作代码

处理ideone的示例,必须稍微改变一下权限。

并且该示例附带了一些评论。

#include <iostream>
#include <vector>
#include <memory>
class _NetVar {};

template <class VARTYPE> 
class NetVar : public _NetVar
{
private:
    VARTYPE Var;
public:
    NetVar(VARTYPE Value)
    {
        Var = Value;
    }
};

请注意,我更改了NetVar&lt;&gt;构造函数和Var属性是公共的......访问它需要AddData和GetData。

不确定您的示例中是否在_NetVar上有一些虚拟方法(在这种情况下,下面的static_pointer_cast可能是dynamic_pointer_cast

与此相关,您可能想要验证NetVar的析构函数(而不仅仅是_NetVar的析构函数)被调用(在ideone上检查,它们在我的示例中工作,因为我使用std::make_shared<NetVar<XX> >(...)

std::vector<std::shared_ptr<_NetVar> > DataVec;
int VecPos;

为以下功能添加了此全局变量。

template <class DATATYPE> void AddData(DATATYPE AddData)
{
    DataVec.push_back(std::make_shared<NetVar<DATATYPE> >(AddData));
}

所以我们在这里创建一个带有新对象shared_ptr的{​​{1}}并将其推送到向量中。

NetVar<DATATYPE>

这里,向量的内容是template <class DATATYPE> DATATYPE GetData() { std::shared_ptr<_NetVar> content = DataVec[VecPos]; std::shared_ptr<NetVar<DATATYPE> > Temp = std::static_pointer_cast<NetVar<DATATYPE> >(content); ++VecPos; return Temp->Var; } ,这就是我们得到的。 shared_ptr需要升级到正确的shared_ptr

现在有一个问题是你必须知道要向上转换的正确类型,否则是未定义的行为。如果你有虚拟方法,你可以使用dynamic_pointer_cast,然后检查null ...但是有一些performance penalties

std::shared_ptr<_NetVar>

最后测试并打印结果。

答案 1 :(得分:1)

一种解决方案是摆脱_NetVar并使用Boost.Any,如:

std::vector<boost::any> DataVec;

template<class T>
void AddData(T data)
{ DataVec.emplace_back(std::move(data)); }

template<class T>
T GetData()
{ return boost::any_cast<T>(DataVec[VecPos++]); }

AddData(32);
AddData(true);
AddData(std::string("test"));

auto Var1 = GetData<int>();
auto Var2 = GetData<bool>();
auto Var3 = GetData<std::string>();