C++ C+中的异构容器+;
我看到了这个漂亮的图形,它根据不同的数据要求对STL容器进行分类,例如: --固定大小与可变大小 --相同类型与不同类型的数据 --已排序与未排序的数据 --顺序存取与随机存取 <>我注意到,在那个图像中,C++ STL没有容器是C++ C+中的异构容器+;,c++,stl,containers,heterogeneous,C++,Stl,Containers,Heterogeneous,我看到了这个漂亮的图形,它根据不同的数据要求对STL容器进行分类,例如: --固定大小与可变大小 --相同类型与不同类型的数据 --已排序与未排序的数据 --顺序存取与随机存取 我注意到,在那个图像中,C++ STL没有容器是 可变尺寸 异构(不同类型的数据) C++没有什么东西吗?< /P> PS-容器的不同属性可能有许多排列,STL中也可能没有提供许多其他排列。如果存储的元素是a,则可以间接存储异构数据。标准库的基本原则是“容器”是同质的;C++标准不考虑诸如“代码> STD::配对<
C++没有什么东西吗?< /P>
PS-容器的不同属性可能有许多排列,STL中也可能没有提供许多其他排列。如果存储的元素是a,则可以间接存储异构数据。标准库的基本原则是“容器”是同质的;C++标准不考虑诸如“代码> STD::配对< /Calp>或<代码> STD::tuple < /Cord>作为容器。(我认为图表是误导性的,因为它把它们当作容器)。如果你需要一个异构容器,你就必须使用一个容器:<代码> Boo::变体或者沿着这些线的东西。 < P>通常,C++容器被设计成使用模板保存单个类型的对象。如果您想要从一个类型派生出不同的类型,您可以存储一个指针容器(我想您也可以有一个void*容器,指向任何东西…),例如std::vector 如果需要完全不相关的类型,可以存储可以安全引用其他类型的对象,例如boost::any boost站点之外的一些示例:
#include <list>
#include <boost/any.hpp>
using boost::any_cast;
typedef std::list<boost::any> many;
void append_int(many & values, int value)
{
boost::any to_append = value;
values.push_back(to_append);
}
void append_string(many & values, const std::string & value)
{
values.push_back(value);
}
bool is_int(const boost::any & operand)
{
return operand.type() == typeid(int);
}
bool is_char_ptr(const boost::any & operand)
{
try
{
any_cast<const char *>(operand);
return true;
}
catch(const boost::bad_any_cast &)
{
return false;
}
}
#包括
#包括
使用boost::any_cast;
typedef std::列出许多;
void append_int(多个&值,int值)
{
boost::any to_append=值;
值。向后推_(以追加_);
}
void append_字符串(多个和值,常量std::字符串和值)
{
值。推回(值);
}
bool is_int(常量boost::any&操作数)
{
返回操作数.type()==typeid(int);
}
bool是字符(const boost::any&操作数)
{
尝试
{
任意_转换(操作数);
返回true;
}
捕获(常量增强::坏的\u任何\u投射&)
{
返回false;
}
}
variant与之类似,但您指定了所有允许的类型,而不是允许容器中的任何类型
std::vectorvec;
向量推回(44);
向量推回(“str”);
向量推回(SomthingElse(55,65))//不准
固定大小的异构容器(如std::tuple
要求在编译时知道类型。如果要创建可变大小的异构容器,只需创建一个std::vector
如果您想要一个在编译时类型未知的异构容器(无论是可变的还是固定大小的),您必须存储指针(或智能指针)对于编译时已知的一种基类型,或者考虑一个容器,如“代码>升压::任何< /COD>”。STL不直接提供固定的或可变大小的容器,它在运行时确定了不同的元素。 <代码> STD::配对< /C> >和<>代码> STD::tuple < /C> >几乎不是C++容器……所以不,STL中没有异构容器,因为不需要内置它们 创建此类容器有几种方法。我推荐的方法有:
- 使用多态性
- 使用变体类型
对于多态性,您可以检查库 当然,由于它是boost,它提供了特定的保证,以确保您只能访问当前处于活动状态的联合成员,并取消了对具有构造函数/析构函数的类的限制,这些类在传统联合中不可用
它还提供了类似于打开类型开关的
static\u visitor
等功能,如果其中一个可能的状态未被访问,则会导致编译错误。一个尚未被Boost接受的库。但建议包含的库旨在:
它提供了一个名为any_collection的好类,它允许通过boost::type_erasure::any拥有一个异构容器:
否则,在C++17中,有一种简单的方法可以实现这一点:
引用上述文章的例子:
namespace andyg{
struct heterogeneous_container{
private:
template<class T>
static std::unordered_map<const heterogeneous_container*, std::vector<T>> items;
public:
template <class T>
void push_back(const T& _t)
{
items<T>[this].push_back(_t);
}
};
// storage for our static members
template<class T>
std::unordered_map<const heterogeneous_container*, std::vector<T>> heterogeneous_container::items;
} // andyg namespace
作者说这是一个玩具式的实现,但我认为这是一个非常聪明的实现方式,与poly_集合或变量向量相比,它有一个简单的优势。我将向您指出这个库。它被实现为真正的异构容器 它不使用多态性,因此也不存储指针。它使用连续内存存储,就像std::vector一样 您可以这样编写代码
typedef StdDataFrame<unsigned long> MyDataFrame;
MyDataFrame df;
std::vector<int> intvec = { 1, 2, 3, 4, 5 };
std::vector<double> dblvec = { 1.2345, 2.2345, 3.2345, 4.2345, 5.2345 };
std::vector<double> dblvec2 = { 0.998, 0.3456, 0.056, 0.15678, 0.00345,
0.923, 0.06743, 0.1 };
std::vector<std::string> strvec = { "Insight", "John Dow", "Alakazam",
"Persian Prince", "Bugs Bunny" };
std::vector<unsigned long> ulgvec = { 1UL, 2UL, 3UL, 4UL, 5UL, 8UL, 7UL, 6UL }
std::vector<unsigned long> xulgvec = ulgvec;
// This is only one way of loading data into a DataFrame instance. There are
// many different ways of doing it. Please see the documentation,
// or dataframe_tester.cc
int rc = df.load_data(std::move(ulgvec), // Index column
std::make_pair("int_col", intvec),
std::make_pair("dbl_col", dblvec),
std::make_pair("dbl_col_2", dblvec2),
std::make_pair("str_col", strvec),
std::make_pair("ul_col", xulgvec));
typedef StdDataFrame MyDataFrame;
MyDataFrame-df;
std::vector intvec={1,2,3,4,5};
向量dblvec={1.2345,2.2345,3.2345,4.2345,5.2345};
向量dblvec2={0.998,0.3456,0.056,0.15678,0.00345,
0.923, 0.06743, 0.1 };
std::vector strvec={“洞察”、“约翰·道”、“阿拉卡萨姆”,
“波斯王子”、“兔八哥”};
std::vector ulgvec={1UL,2UL,3UL,4UL,5UL,8UL,7UL,6UL}
std::vector xulgvec=ulgvec;
//这只是将数据加载到DataFrame实例中的一种方法
//有很多不同的方法。请参阅文档,
//或dataframe_tester.cc
int rc=df.load_data(std::move(ulgvec))//索引列
std::制作成对(“int col”,intvec),
标准::制作双(“dbl\U列”,dblvec),
标准::制作双(“dbl\U列2”,dblvec2),
标准::制作成对(“str_col”,strvec),
std::make_pair(“ul_col”,xulgvec));
从这张图片中,我可以看出其中有那么多
enum { Type1, Type2, ... } _type;
union {
SomeType1 _1;
SomeType2 _2;
...
} _u;
namespace andyg{
struct heterogeneous_container{
private:
template<class T>
static std::unordered_map<const heterogeneous_container*, std::vector<T>> items;
public:
template <class T>
void push_back(const T& _t)
{
items<T>[this].push_back(_t);
}
};
// storage for our static members
template<class T>
std::unordered_map<const heterogeneous_container*, std::vector<T>> heterogeneous_container::items;
} // andyg namespace
andyg::heterogeneous_container c;
c.push_back(1);
c.push_back(2.f);
c.push_back('c');
struct LocalStruct{};
c.push_back(LocalStruct{});
typedef StdDataFrame<unsigned long> MyDataFrame;
MyDataFrame df;
std::vector<int> intvec = { 1, 2, 3, 4, 5 };
std::vector<double> dblvec = { 1.2345, 2.2345, 3.2345, 4.2345, 5.2345 };
std::vector<double> dblvec2 = { 0.998, 0.3456, 0.056, 0.15678, 0.00345,
0.923, 0.06743, 0.1 };
std::vector<std::string> strvec = { "Insight", "John Dow", "Alakazam",
"Persian Prince", "Bugs Bunny" };
std::vector<unsigned long> ulgvec = { 1UL, 2UL, 3UL, 4UL, 5UL, 8UL, 7UL, 6UL }
std::vector<unsigned long> xulgvec = ulgvec;
// This is only one way of loading data into a DataFrame instance. There are
// many different ways of doing it. Please see the documentation,
// or dataframe_tester.cc
int rc = df.load_data(std::move(ulgvec), // Index column
std::make_pair("int_col", intvec),
std::make_pair("dbl_col", dblvec),
std::make_pair("dbl_col_2", dblvec2),
std::make_pair("str_col", strvec),
std::make_pair("ul_col", xulgvec));