【问题标题】:Insert element in map of boost::any and return reference to it在 boost::any 的映射中插入元素并返回对它的引用
【发布时间】:2014-11-01 11:25:30
【问题描述】:

我有一个存储许多实体的类。我希望能够添加和删除为每个实体存储的任意(命名)属性。

我使用这张地图来存储属性:

std::map<std::string, boost::any> m_properties;

为了添加属性,我将MyProperty&lt;T&gt; 的实例添加到属性映射中。 MyProperty&lt;T&gt; 为我的每个 m_size 实体存储 T 类型的属性。

template <class T>
MyProperty<T>& addProperty(const std::string& name, const T& defaultValue = T())
{
    assert(!m_properties.count(name));
    m_properties[name] = MyProperty<T>(m_size, defaultValue);
    return boost::any_cast<MyProperty<T>&>(m_properties[name]);
}

这行得通,但对我来说,我必须创建一个 MyProperty&lt;T&gt; 的实例,忘记它的类型,然后在下一行将其重新转换,这似乎很麻烦。

有没有更好、更直接的方法将属性插入地图并返回对它的引用?

我想尽可能避免复制 MyProperty 实例,因为它包含大量数据。

编辑:看来我对问题的重点还不够清楚。我不担心演员表的性能,因为在我的用例中,我只会添加少数属性。但是,我一直在寻找编码风格方面“更好”的解决方案,因为我一直在努力为手头的任务找到最简单、最优雅的解决方案。

【问题讨论】:

  • @Niall 并不总是插入。此外,它具有相同的演员要求

标签: c++ boost map


【解决方案1】:

这行得通,但对我来说,我必须创建一个 MyProperty 的实例,忘记它的类型,然后将其转换回下一行,这似乎很麻烦。

如果你不想忘记类型,你不应该使用boost::any,因为boost::any确实精确地做到这一点:从界面中删除类型。

您可以考虑改用boost::variant(尽管它需要进行另一组设计权衡)

【讨论】:

  • 是的,我明白了,这也是我想要的“异构”地图,即当我稍后检索属性时,我同意我必须使用演员表。当我创建实例并在之前的行上有类型信息时,进行强制转换似乎很愚蠢......
  • 他仍然需要一个演员表,也许以其他方式调用,但仍然是演员表。
  • @user1095108 我的意思是,返回实际的变体可能会很方便。很抱歉在这方面不清楚。
【解决方案2】:

我会试试这个:

template <class T>
MyProperty<T>& addProperty(const std::string& name, const T& defaultValue = T())
{
    assert(!m_properties.count(name));
    auto const p(m_properties.insert(name, MyProperty<T>(m_size, defaultValue)));
    assert(p.second);
    return boost::any_cast<MyProperty<T>&>(p.first->second);
}

“演员表”很便宜,你可以查看any的源代码。如果你自己写any,它也可以变得更便宜。否则,如果复制太慢,您可以尝试移动,或者就地构建。

很久以前我也遇到过类似的问题,我通过存储::std::unique_ptrs 解决了它(您也可以使用::std::shared_ptrs,但这些更重)。但是boost::any 到目前为止只适用于::std::shared_ptrs。

template <class T>
MyProperty<T>& addProperty(const std::string& name, const T& defaultValue = T())
{
    assert(!m_properties.count(name));
    auto const ptr(::std::make_shared<MyProperty<T> >(defaultValue));
    auto const p(m_properties.insert(name, ptr));
    assert(p.second);
    return *ptr;
}

【讨论】:

  • 谢谢,我想这已经更高效/优雅了(尽管由于insert()...的返回值令人困惑,可读性也降低了)。现在要是我能以某种方式摆脱演员阵容就好了……
  • @ValarDohaeris “cast”其实是函数模板的实例化和调用。它会被内联,没什么大不了的。
  • 我认为您在第二个示例中以某种方式混淆了默认值和映射(类成员),至少它对我没有意义。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-03-07
相关资源
最近更新 更多