gpt4 book ai didi

C++ 在一个集合中存储多种数据类型

转载 作者:塔克拉玛干 更新时间:2023-11-03 02:24:11 28 4
gpt4 key购买 nike

问题:我希望我的代码的不同部分能够访问一个公共(public)集合,该集合以每个对象的类型已知的方式存储不同类型的对象,并且至关重要的是,检索来自集合的应该在编译时进行类型检查。 (我意识到这与之前提出的问题很接近,但请继续阅读,这更具体一些。)

举一个具体的例子,我想要做以下事情:

// 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 key 。有没有解决的办法?或者至少是一种减少滥用的方法?我试过使用独特的 int在从 static int 生成的每个 key 中(并使 std::map 键类型为 int ),但出于线程原因,我想尽可能避免静态。

3) 避免使用boost::any std::map是否合理类型为 <const KeySupertype *, void *>并使用 static_cast<T>而不是 any_cast

最佳答案

1) 我觉得不错,一个聪明的解决方案

2) 我猜你担心有人会复制 key 并且它的地址会改变。如果这是您的顾虑,请在您的 KeySuperType 中保留一个“原始地址”字段.构建时将原始地址设置为此,复制时将原始地址设置为右手(源)的原始地址。使用此原始地址访问 map 内容。我真的想不出一个编译时的解决方案,因为在编译时,编译单元不会相互了解。您可以在链接时最早为键分配唯一 ID,获取全局变量的地址有点等同于此。我可以看到这个解决方案的唯一弱点是,如果您在两个动态共享库中定义相同的 key 而不使用 extern ,他们将默默地拥有自己的具有不同地址的 key 版本。当然,如果所有东西都进入同一个二进制文件,你就不会有这个问题,因为没有 extern 的两个声明。将导致“多重声明”链接器错误。

3) 如果您对 boost::any 有疑问取决于 boost(比你想象的更好),然后实现 any自己,这出奇的简单。如果问题是性能,那么 static_cast<>对我来说似乎也可以,只要您保留 PropertiesMap 的内部结构即可远离那些不知道自己在做什么的人......

关于C++ 在一个集合中存储多种数据类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9775824/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com