StringMap moves its Allocator. What happens with a reference?

A common pattern is having one allocator serve several data structures, for instance

typedef StringMap<bool, BumpPtrAllocator&> SymbolTable;

BumpPtrAllocator Allocator;

SymbolTable Sym1;

SymbolTable Sym2;

Sym2 = std::move(Sym1);

With gcc 4.9.1 this fails

/llvm/include/llvm/ADT/StringMap.h:
In instantiation of ‘llvm::StringMap<ValueTy, AllocatorTy>::StringMap(llvm::StringMap<ValueTy, AllocatorTy>&&)
[with ValueTy = llvm::MCSymbol*; AllocatorTy = llvm::BumpPtrAllocatorImpl<>&]’:

/llvm/include/llvm/ADT/StringMap.h:243:74:
error: invalid initialization of non-const reference of type ‘llvm::BumpPtrAllocatorImpl<>&’
from an rvalue of type ‘std::remove_reference<llvm::BumpPtrAllocatorImpl<>&>::type {aka llvm::BumpPtrAllocatorImpl<>}’
: StringMapImpl(std::move(RHS)), Allocator(std::move(RHS.Allocator)) {}

due to the inability to move the allocator reference where in fact we wish to copy it.

With Visual C++ 2013 the code compiles and apperantly copies the allocator reference.

What is the proper way to move such StringMaps or other data structures using an allocator reference?

Yaron

A common pattern is having one allocator serve several data structures,

Given that we don't have any uses or tests of this in tree (since it
doesn't work in StringMap and I assume it doesn't work in any of our other
ADTs either?) I suspect it's not quite as common as it may appear. I'm not
sure it's even valid for C++ standard allocators (which LLVM's allocators
are not implementations of), is it?

for instance

typedef StringMap<bool, BumpPtrAllocator&> SymbolTable;
BumpPtrAllocator Allocator;
SymbolTable Sym1;
SymbolTable Sym2;
Sym2 = std::move(Sym1);

With gcc 4.9.1 this fails

/llvm/include/llvm/ADT/StringMap.h:
  In instantiation of 'llvm::StringMap<ValueTy,
>::StringMap(llvm::StringMap<ValueTy, AllocatorTy>&&)
  [with ValueTy = llvm::MCSymbol*; AllocatorTy =
llvm::BumpPtrAllocatorImpl<>&]':

/llvm/include/llvm/ADT/StringMap.h:243:74:
  error: invalid initialization of non-const reference of type
'llvm::BumpPtrAllocatorImpl<>&'
  from an rvalue of type
'std::remove_reference<llvm::BumpPtrAllocatorImpl<>&>::type {aka
llvm::BumpPtrAllocatorImpl<>}'
       : StringMapImpl(std::move(RHS)),
Allocator(std::move(RHS.Allocator)) {}

due to the inability to move the allocator reference where in fact we wish
to copy it.

With Visual C++ 2013 the code compiles and apperantly copies the allocator
reference.

What is the proper way to move such StringMaps or other data structures
using an allocator reference?

I imagine the correct way to do this would be to write a wrapper/proxy
allocator (with a raw Allocator* inside it that can then be correctly
copied/moved/whatever). Though I could be wrong/haven't given this lots of
thought.

- David

Thanks, I worked around this in my application by not moving the StringMap but modifying it instead.
The code is not as clean as it would be with a move, though.