0

我正在尝试在 C++ 中创建一个通用存储类。如果您查看下面的代码,我想存储string/的地图AnyType并访问它们。

  class StoresTestC
  {
  public:
    template < class SettingsType >
    std::map< std::string, SettingsType >* getStore(std::string const&);
  private:
    std::map< std::string, void* > stores_;
  };

  template < class SettingsType >
  std::map< std::string, SettingsType >* StoresTestC::getStore(std::string const& name)
  {
    if (stores_.count(name) > 0)
    {
      void* temp = this->stores_[name];
      return (std::map< std::string, SettingsType >*)(temp);
    }
    else
    {
      std::map< std::string, SettingsType > * result = new std::map< std::string, SettingsType > ();
      this->stores_[name] = result;
      return result;
    }
  }

我看到这样做有两个明显的危险:

  1. 如果我用错误的方式调用它SettingsType/name我将调用错误的演员阵容,据我所知(我可能是错的)将导致未定义的行为。

  2. 它会造成内存泄漏,但我有一个解决方案(这里也有两个很长的内容)。

还有什么其他可能出错的地方吗?你能预见到吗?

4

3 回答 3

2

首先退后一步,确保你真的想要这样做。然后再看一次你的设计。

好的,你还需要这个能力吗?

std::map<std::string, boost::any>boost::any始终是map类型的地方使用。然后,当您使用any_cast或任何机制将项目取回时,您可以保证它是正确的类型或者它会抛出,因此您永远不会冒未定义行为的风险。此外,由于any按值计算,您也不会出现内存泄漏。

我还应该注意,在您的原始解决方案中,如果您使用 ashared_ptr<void*>它会记住如何删除存储在其中的原始类型,shared_ptr从而消除您提到的内存泄漏。

编辑:我看不到任何其他明显的技术问题。但是请注意,拥有这样的地图可能/可能会给未来的维护者带来认知(“grokking”)问题,并且确实会增加代码的复杂性。

于 2012-12-20T17:47:16.987 回答
1

是的,您对第 1 点的怀疑是正确的(正如您提到的,第 2 点应该是可以解决的,但请考虑应该正确调用包含的地图的析构函数)。

SettingsType如果不提供客户端跟上的简单机制和std::string同步的“类型名”表示,我不会放过这样的接口。一个简单的错字可能会搞砸整个事情。我认为boost::any只要您尝试将值转换为所需/预期的结果类型,这只会表达这一点。

为什么你需要std::string在这里代表?例如,如果您使用 RTTI,您可以隐藏用于stores_使用的密钥typeid()

于 2012-12-20T17:56:48.207 回答
0

既然您必须将类型作为模板参数传递来获取地图,那么每种类型只有一个地图是否可行?

namespace StoresTest {
  template<typename T>
  struct MapStruct {
    static std::map<std::string, T> the_map;
  };

  template<typename T> std::map<std::string, T> MapStruct<T>::the_map;

  template<typename T>
  inline std::map<std::string, T>& getStore()
  { return MapStruct<T>::the_map; }
}

然后例如,您可以Foo通过执行获取具有值类型的地图

std::map<std::string, Foo>& foo_map = StoresTest::getStore<Foo>();

您不再需要为string类型命名,但如果您有其他原因需要它,可以添加它。

于 2012-12-20T17:55:22.827 回答