模板化存储std::vector中的多种不同类型

Templatized Storing Multiple Different Types In std::vector

本文关键字:同类型 vector 存储 std      更新时间:2023-10-16

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

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

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等外部库。

矢量应为:

std::vector<_NetVar *> DataVec;

或高级指针

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

这样就可以存储子类的实例,而不是将它们切片到基类。

在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<>构造函数和Var属性为公共。。。访问它所需的AddData和GetData。

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

与此相关的是,您可能需要验证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));
}

因此,在这里我们创建了一个带有新对象NetVar<DATATYPE>shared_ptr,并将其推送到向量中。

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;
}

这里,向量的内容是std::shared_ptr<_NetVar>,所以这就是我们得到的。该shared_ptr需要被上传到正确类型的shared_ptr

现在有一个问题是,您必须知道向上转换的正确类型,否则就是未定义的行为。如果你有虚拟方法,你可以使用dynamic_pointer_cast,然后检查null。。。但这会对的性能造成一些影响

int main() {
    AddData<int>(32);
    AddData<bool>(true);
    AddData<std::string>("Test");
    auto Var1 = GetData<int>();
    auto Var2 = GetData<bool>();
    auto Var3 = GetData<std::string>();
    std::cout << Var1 << std::endl;
    std::cout << Var2 << std::endl;
    std::cout << Var3 << std::endl;
    return 0;
}

最后测试并打印结果。

一个解决方案是去掉_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>();
相关文章: