Templates and Compilers Make My Head Spin

I found a bug in Visual C++ 7.1 today. I wanted to write my own C++ allocator that I could use in a std::set. Since std::allocator does 90% of what I need, I derived my own allocator from it and reimplemented two (actually, two + rebind) things:

template<typename T>
struct Win32Allocator : public std::allocator<T> {
    template<typename U>
    struct rebind {
        typedef Win32Allocator<U> other;
    };

    pointer allocate(size_type count, void* /*hint*/ = 0) {
        // ...
    }

    void deallocate(pointer p, size_type /*size*/) {
        // ...
    }
};

Looks good. Works fine for vector, list, map. Also works fine for std::set in gcc, but not in VC++ 7.1, the compiler in which I need this to work. VC++ gives the following error:

C:\Program Files\Microsoft Visual Studio .NET 2003\Vc7\include\set(24) : error C2248: 'Win32Allocator<T>::rebind<U>::other' : cannot access inaccessible typedef
declared in class 'Win32Allocator<T>'

Wut! Everything is public! How can the typedef be inaccessible? Oddly enough, if I make the typedef private, the format of the error message changes… Something fishy is going on. Some googling gives the following conclusions:

  • Only one other person has run into this and documented the problem online.
  • Nobody has an answer.
  • This technique works fine in VC++ 6 and 7.0.
  • The annoying and semi-ugly workaround of implementing your own allocator without deriving from std::allocator works fine.

I decided to not derive from std::allocator, but bleh. That plus unexpected Boost.Python behavior has made this a headache-inducing day, and I’ve only been up for six hours.

1 thought on “Templates and Compilers Make My Head Spin”

Leave a Reply

Your email address will not be published. Required fields are marked *