C++在一个集合中存储多个数据类型
C++ store multiple data types in one collection
问题:我希望代码的不同部分能够访问一个公共集合,该集合存储不同类型的对象,这样每个对象的类型都是已知的,而且最重要的是,在编译时应该对从集合中检索的内容进行类型检查。(我意识到这与之前提出的问题很接近,但请继续阅读,这更具体一些。)
举一个具体的例子,我想要做以下事情:
// Stuff that can go in the collection:
enum Key { NUM_APPLES /* (unsigned int) */, APPLE_SIZE /* (double) */ }
map<Key, Something> collection;
unsigned int * nApples = collection.find(NUM_APPLES);
int * appleSize = collection.find(APPLE_SIZE); // COMPILATION ERROR - WRONG TYPE
我的解决方案:到目前为止,我已经使用boost::any
:设计了以下解决方案
关键:
using namespace std;
using namespace boost::any;
struct KeySupertype
{
protected:
// Can't create an instance of this type
KeySupertype() {}
private:
// Can't copy
KeySupertype& operator = (const KeySupertype& other) {}
KeySupertype(const KeySupertype& other) {}
};
template <typename Type>
struct Key : public KeySupertype
{
public:
Key() {}
};
藏品:
class PropertiesMap
{
public:
template<typename T>
T * find(Key<T> & key);
/* Skipping erase, insert and other methods for brevity. */
private:
map<const KeySupertype *, any> myAnyMap;
};
template <typename T>
T * PropertiesMap::find(Key<T> & key)
{
const map<const KeySupertype *, any>::iterator it = myAnyMap.find(&key);
if(it == myAnyMap.end())
return NULL;
return any_cast<T>(&it->second);
}
用法:
static const Key<unsigned int> NUM_APPLES;
static const Key<double> APPLE_SIZE;
PropertiesMap collection;
/* ...insert num apples and apple size into collection ...*/
unsigned int * const nApples = collection.find(NUM_APPLES);
int * const nApples = collection.find(NUM_APPLES); // COMPILATION ERROR
通过这种方式,根据每个Key
的模板参数对类型信息进行编码,因此在与集合交互时将强制执行该类型。
问题:
1) 这是实现我目标的合理方式吗?
2) 糟糕的一点是,集合使用Key
对象的地址作为内部std::map
键。有办法绕过这个吗?或者至少是一种减少滥用的方法?我曾尝试在从static int
生成的每个密钥中使用唯一的int
(并使std::map
密钥类型为int
),但出于线程原因,如果可能的话,我希望避免静态。
3) 为了避免使用boost::any
,使std::map
为<const KeySupertype *, void *>
类型并使用static_cast<T>
而不是any_cast
是否合理?
1)看起来不错,是一个聪明的解决方案
2) 我想你担心有人会复制钥匙,它的地址会改变。如果您担心这一点,请在KeySuperType
中保留一个"原始地址"字段。在构建过程中,将原始地址设置为该地址,在复制过程中将原始地址设为右手(源)的原始地址。使用此原始地址访问地图内容。我真的想不出一个编译时的解决方案,因为在编译时,编译单元不会互相了解。您可以在链接时间的最早时间为键分配唯一的ID,而获取全局变量的地址就相当于此。我能看到的这个解决方案的唯一弱点是,如果你在两个没有extern
的动态共享库中定义同一个密钥,它们将拥有自己版本的不同地址的密钥。当然,如果所有东西都进入同一个二进制文件,就不会有这个问题,因为两个没有extern
的声明会导致"多个声明"链接器错误。
3) 如果你的boost::any
问题取决于boost(这比你想象的更合适),那么你自己实现any
,它非常简单。如果问题是性能,那么static_cast<>
在我看来也可以,只要你保留PropertiesMap
的内部远离那些不知道自己在做什么的人。。。
- 多维数组存储三种不同的数据类型?
- 生成一个类Name_class并将两种数据类型存储在一个向量中
- C++:灵活且能够存储多种数据类型的数组
- 将元音与字符串数据类型的字符串分开,并将其存储在新字符串中
- 什么是在C 中存储结果INT*的最佳数据类型
- 如何将预定义数据类型的值存储到数组中并输出它
- 在 JavaScript 中,值的数据类型存储在何处以及如何存储?
- 如何制作一个为程序的每个运行中存储不同数据类型的向量
- 将临时值存储为某种数据类型时,算术运算的标准规则是什么
- 通用B树,用于存储自定义对象/数据类型
- 如何检查程序是否超过数据类型存储
- 哪种数据类型用于存储文件名和文件大小的使用
- 如何在一个向量中存储具有不同数据类型的对象
- C++ 从文本文件数据类型读取为结构,并将数据存储在列表的向量中
- 如何在用户数据中存储值类型
- 在 C 程序中存储"binary"数据类型
- 您能否安全地将 char 数据存储在 int 数据类型中
- 用于存储大数字的数据类型
- 将类成员存储为RapidXML数据类型
- 将多调数据类型存储到unique_ptr向量中