简体   繁体   English

带有自定义分配器的std :: unordered_set

[英]std::unordered_set with custom allocator

Good evening, 晚上好,

RESOLUTION: The issue was coming from the explicit keyword from my allocator ctors. 解决方案:问题来自我的分配器控制器的显式关键字。

EDIT: I've been finally able to locate the issue. 编辑:我终于能够找到问题。 It's seems to come from the move ctor of unordered_set when it's used with some custom allocator. 与某些自定义分配器一起使用时,它似乎来自unordered_set的移动ctor。 Still digging. 还在挖。

EDIT: Weird thing is that there is no issue when using my custom allocator and a std::vector. 编辑:奇怪的是,使用我的自定义分配器和std :: vector时没有问题。

Why do I get an error message when I try to copy an element from : 尝试从中复制元素时,为什么会收到错误消息:

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

to : 至 :

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

as follows : 如下 :

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

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

    return kSet;
}

The exact error message is given in french, so the approximate translation would be : 确切的错误消息以法语给出,因此近似翻译为:

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

Note that if I don't put the kSet.insert(), I don't get the error. 请注意,如果我不放置kSet.insert(),则不会收到该错误。

The typedefs are done in the scope of CProfiler. typedef在CProfiler的范围内完成。

I've been stuck for days now, and it doesn't seem to come from the hasher as one could expect. 我已经被困了好几天了,它似乎并没有像人们期望的那样来自哈希器。 Any idea is welcome, and sorry if the post isn't properly formed as it's my first post on StackOverflow. 欢迎提出任何想法,如果这篇文章的格式不正确,这是我第一次在StackOverflow上发表,抱歉。

PS : As requested here is the code snippet. 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;
        };

Because, unfortunately, your two containers are different types. 因为不幸的是,您的两个容器是不同的类型。 And so, consequently are their iterators. 因此,它们的迭代器也是如此。 This problem is what SCARY iterators are designed to resolve - when containers should be considered equivalent for iteration purposes, even though their types are distinct. 这个问题是SCARY迭代器旨在解决的问题-当出于迭代目的应将容器视为等效时,即使它们的类型不同。 The workaround is either to unify your container types (maybe deriving one from another), or rewrite not to depend on iterator-based algorithms (dereference and copy elements individually). 解决方法是要么统一您的容器类型(可能是从另一个容器派生),要么重写它而不依赖于基于迭代器的算法(分别引用和复制元素)。

EDIT: I was able to repro with a simple example, which has nothing to do with the insert() call, but rather the rvalue move ctor of the temporary kSet. 编辑:我能够用一个简单的示例进行复制,该示例与insert()调用无关,而只是临时kSet的右值移动ctor。 With C++11, there are a few new requirements for your custom allocator - particularly the rebind type function. 使用C ++ 11,自定义分配器有一些新要求-特别是rebind类型函数。 See here for more info. 有关更多信息,请参见此处

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;
};

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM