2

I'm getting an internal compiler error in Visual Studio 2013. The exact error is

c:\program files (x86)\microsoft visual studio 12.0\vc\include\xmemory0(487): fatal error     C1001: An internal error has occurred in the compiler.
2>  (compiler file 'f:\dd\vctools\compiler\utc\src\p2\ehexcept.c', line 1483)
2>   To work around this problem, try simplifying or changing the program near the locations listed above.

Which points me to this code in the implementation of std::allocator_traits:

static _Alloc select_on_container_copy_construction(
    const _Alloc& _Al)
    {   // get allocator to use
    return (_Alloc_select::_Fn(0, _Al));
    }

From that I suppose the problem is related to an implementation I've made for a custom allocator. This allocator is a class template to wrap around simpler allocators that I use in my project and that don't conform to the standard (hence the need for wrapping). The wrapper is as follows:

template<class BaseAlloc_, class T_>
    class StdAllocator : public BaseAlloc_ {
    public:
        // Public types
        typedef T_              value_type;
        typedef T_*             pointer;
        typedef const T_*       const_pointer;
        typedef T_&             reference;
        typedef const T_&       const_reference;
        typedef std::size_t     size_type;
        typedef std::ptrdiff_t  difference_type;

    public:
        // Convert an allocator<T_> to allocator<U_>
        template<typename U_>
        struct rebind {
            typedef StdAllocator<BaseAlloc_,U_> other;
        };

    public:
        inline explicit StdAllocator():BaseAlloc_() {}
        inline explicit StdAllocator(BaseAlloc_ _b) :BaseAlloc_(_b) {}
        inline ~StdAllocator() {}
        inline explicit StdAllocator(StdAllocator const& _x) :BaseAlloc_(_x) {}
        template<typename U>
        inline explicit StdAllocator(StdAllocator<BaseAlloc_,U> const&) :BaseAlloc_() {}

        //    address
        inline pointer address(reference r) { return &r; }
        inline const_pointer address(const_reference r) { return &r; }

        //    memory allocation
        inline pointer allocate(size_type _cnt,
            typename std::allocator<void>::const_pointer = 0) {
            return BaseAlloc_::allocate<T_>(_cnt);
        }
        inline void deallocate(pointer _p, size_type _cnt) {
            BaseAlloc_::deallocate(_p,_cnt);
        }

        //    size
        inline size_type max_size() const {
            return std::numeric_limits<size_type>::max() / sizeof(T_);
        }

        //    construction/destruction
        inline void construct(pointer p, const T_& t) { new(p)T_(t); }
        inline void destroy(pointer _p) { 
            _p; // Work around for visual studio incorrect warning
            _p->~T_();
        }

        inline bool operator==(StdAllocator const&) { return true; }
        inline bool operator!=(StdAllocator const& a) { return !operator==(a); }
    };

Given Visual Studio doesn't provide any more information, I don't know how to tackle this problem.

Jarod42
  • 203,559
  • 14
  • 181
  • 302
technik
  • 39
  • 4
  • 2
    An ICE is always a bug in the compiler. Report it, e.g. to http://connect.microsoft.com – dyp Apr 13 '14 at 14:06
  • Not sure why the copy and default constructors are explicit.. Also, the `inline` is just noise here. – dyp Apr 13 '14 at 14:08
  • No its not always a bug in the compiler. You've written code, usually template code that is so complex that the compiler is incapable of resolving the issue. Devide and conquer. Start with something that does compile, and replace parts with the code that doesn't until you find out what you did wrong. And you will find that your trying to do something the compiler was never intended to do. This is not a what we refer to as a bug. – Dan Apr 13 '14 at 14:12
  • `BaseAlloc_::template allocate(_cnt);` <-- the `template` keyword is required here. – dyp Apr 13 '14 at 14:12
  • 2
    @Dan I've yet to see this error message relating to something like memory exhaustion or violating of implementation limits. Even if, that error message isn't helpful at all. – dyp Apr 13 '14 at 14:13
  • When I've seen it its usually due to circular references where template arguments cannot be resolved. I agree that its a terribly useless error. – Dan Apr 13 '14 at 14:21
  • @dyp why is the `template` keyword necessary there? given T_ is already a template parameter of the class itself, I'd think the expression is properly defined – technik Apr 13 '14 at 17:01
  • As suggested by @Dan, I decided to go for the divide and conquer strategy. My first step was to remove the unnecessary `inline` and `explicit` keywords to make it more clear, as noted by @dyp. Surprisingly enough removing the `explicit` keyword from the default constructor and copy-constructor was all that Visual Studio needed, and now the code compiles successfully. So, now I don't know whether it is a bug on Visual Studio, or it is illegal to use explicit with copy-constructor or default constructor. – technik Apr 13 '14 at 17:13
  • 1
    @technik See [Where and why do I have to put the “template” and “typename” keywords?](http://stackoverflow.com/questions/610245/where-and-why-do-i-have-to-put-the-template-and-typename-keywords). For example, `BaseAlloc_::allocate(_cnt);` would be ambiguous; also, the `template` keyword allows earlier syntax checks. // An `explicit` default/copy ctor is allowed; as I said before, this is probably a compiler bug. – dyp Apr 13 '14 at 17:35

1 Answers1

1

I read this and the linked article only to see half an hour later that one comment answered this question: "Surprisingly enough removing the explicit keyword from the default constructor and copy-constructor was all that Visual Studio needed, and now the code compiles successfully." That did the trick for me. I copied it to an answer not to steal it but to expose it.

tiands
  • 142
  • 2
  • 5