首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >C++在一个集合中存储多个数据类型

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

Stack Overflow用户
提问于 2012-03-19 18:31:59
回答 1查看 3.8K关注 0票数 5

问题:我希望我的代码中不同的部分能够访问一个公共集合,该集合存储不同类型的对象,这样每个对象的类型都是已知的,而且最重要的是,应该在编译时检查从集合中检索的类型。(我知道这与之前提出的问题很接近,但请大家继续阅读,这是比较具体的问题。)

为了给出一个具体的例子,我想做以下几点:

代码语言:javascript
运行
复制
// 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设计了以下解决方案

关键是:

代码语言:javascript
运行
复制
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() {}
};

收藏:

代码语言:javascript
运行
复制
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);
}

用法:

代码语言:javascript
运行
复制
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键。有办法绕道吗?或者至少是一种减少误用的方法?我尝试在每个由int生成的键中使用唯一的static int (并将std::map键类型为int),但如果可能的话,出于线程的原因,我希望避免静态操作。

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

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2012-03-20 16:06:21

在我看来,这是个很好的解决方案。

2)我想你担心有人会抄袭这把钥匙,它的地址也会改变。如果这是您关心的问题,请在您的KeySuperType中保留“原始地址”字段。在构造期间将原始地址设置为此,在复制过程中将原始地址设置为右手(源)的原始地址。使用此原始地址访问地图内容。我真的想不出这个编译时的解决方案,因为在编译时,编译单元之间不会相互了解。您可以在链接时间内最早将唯一的ID分配给密钥,获得全局变量的地址与此等价。我在这个解决方案中看到的唯一缺点是,如果您在两个没有extern的动态共享库中定义相同的密钥,它们将默默地拥有具有不同地址的密钥版本。当然,如果所有东西都进入相同的二进制文件中,您就不会遇到这个问题,因为没有extern的两个声明将导致一个“多声明”链接器错误。

3)如果您的boost::any问题取决于boost (这比您认为的要好),那么自己实现any是非常简单的。如果问题在于性能,那么static_cast<>在我看来也是可以的,只要你把你的PropertiesMap的内部设备远离那些不知道他们在做什么的人。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/9775824

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档