2013-04-29 81 views
0

晚上好,的std :: unordered_set与自定义分配器

解决方案:这个问题是由明确的关键字来从我的分配器构建函数。

编辑:我终于能够找到问题。它似乎来自unordered_set的移动ctor,当它与一些自定义分配器一起使用时。仍在挖掘。

编辑:奇怪的是,使用我的自定义分配器和std :: vector时没有问题。

为什么我得到一个错误信息,当我尝试的元素从复制:

typedef std::unordered_set< const CScopeProfiler* > CInternalScopeProfilersSet; 

到:

typedef std::unordered_set< const CScopeProfiler*, std::hash< const CScopeProfiler* >, std::equal_to< const CScopeProfiler* >, CAllocator< const CScopeProfiler* > > CScopeProfilersSet; 

如下:

CProfiler::CScopeProfilersSet CProfiler::ScopeProfilersRegistry() const 
{ 
    CScopeProfilersSet kSet; 

    kSet.insert(*(m_pkRegister->begin())); 

    return kSet; 
} 

确切的错误信息用法语给出,所以近似的翻译将是:

Error 1 error C2664: 'std::_Hash<_Traits>::_Hash(const std::_Uhash_compare<_Kty,_Hasher,_Keyeq> &,const GameForge::Core::CAllocator<T> &)' : impossible to convert second parameter of 'std::_Wrap_alloc<_Alloc>' to 'const GameForge::Core::CAllocator<T> &' c:\program files (x86)\microsoft visual studio 11.0\vc\include\unordered_set 195 1 

请注意,如果我不把kSet.insert(),我没有得到错误。

typedef在CProfiler的范围内完成。

我一直坚持了几天,它似乎并没有像一个人所期望的那样来自于哈希。任何想法都是值得欢迎的,如果帖子的格式不正确,我很抱歉,因为这是我在StackOverflow上的第一篇文章。

PS:按照要求,这里是代码片段。

namespace GameForge 
{ 
    namespace Core 
    { 
     class CAllocationsHistogram; 

     // Ensure profiling code isn't profiled. 
     class GF_API CProfiler 
     { 
     public: 
      class CScopeRun; 

      class GF_API CScopeProfiler 
      { 
       friend CProfiler; 
       friend CScopeRun; 

      public: 
       CScopeProfiler(const char* pcLabel); 
       ~CScopeProfiler(); 
      }; 

      class GF_API CScopeRun 
      { 
       friend CProfiler; 

      public: 
       CScopeRun(CScopeProfiler& rkScopeProfiler); 
       ~CScopeRun(); 
      }; 

      typedef std::unordered_set< const CScopeProfiler*, 
             std::hash< const CScopeProfiler* >, 
             std::equal_to< const CScopeProfiler* >, 
             CAllocator< const CScopeProfiler* > > CScopeProfilersSet; 

     private: 
      typedef std::unordered_set< const CScopeProfiler* > CInternalScopeProfilersSet; 

     public: 
      CScopeProfilersSet ScopeProfilersRegistry() const; 

     protected: 
      CProfiler(); 
      ~CProfiler(); 

     private: 
      CInternalScopeProfilersSet* m_pkRegister; 
     }; 
+2

我不认为,请发布一个展示此行为的最小完整代码片段。 – 2013-04-29 20:43:07

+0

......重点确实在**最小**代码上。 – 2013-04-29 21:20:40

+0

好吧,因为我不太了解此事,所以发布最小代码非常困难。 – 2013-04-29 21:24:29

回答

0

因为,不幸的是,你的两个容器是不同的类型。所以,他们的迭代器就是这样。这个问题是SCARY迭代器设计用于解决的问题 - 当迭代目的容器应该被认为是等价的,尽管它们的类型是不同的。解决方法是统一你的容器类型(也许从另一个派生),或者重写不要依赖基于迭代器的算法(单独提取和复制元素)。

编辑: 我可以用一个简单的例子,这无关与插入()调用,而是临时KSET的右值移动构造函数来摄制。使用C++ 11,您的自定义分配器有一些新要求 - 特别是重新绑定类型函数。有关更多信息,请参见here

template<typename T> 
struct CAllocator : allocator<T> 
{ 
    CAllocator(){} 

    template <class U> 
    CAllocator(CAllocator<U> const &) {} 

    // This required to ensure custom allocator is propagated in move semantics 
    template <class U> 
    struct rebind 
    { 
     typedef CAllocator<U> other; 
    }; 
}; 

typedef std::unordered_set< const CScopeProfiler*, std::hash< const CScopeProfiler* >, std::equal_to< const CScopeProfiler* >, CAllocator< const CScopeProfiler * > > CScopeProfilersSet; 

CScopeProfilersSet ScopeProfilersRegistry() 
{ 
    CScopeProfilersSet kSet; 
    return kSet; 
}; 
+0

的代码实际上没有通过迭代器周围 - 它传递(引用)*值*。 – 2013-04-29 21:01:08

+0

这是真的 - 不完整的代码,我是假设反引用可能是一个错误,并打算在编译器错误味精,这表明直接分配类型之间(一个STL的默认和其他自定义)不匹配,这表明容器类型不匹配。 - – 2013-04-29 21:07:31

+0

@Adrian如果你单独的事情了,会发生什么: 汽车及ELEM = *(m_pkRegister->开始()); kSet.insert(elem); – 2013-04-29 21:09:37

相关问题