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.
Non-template-hyper code is easier to use than template-hyper code.