1
votes

I have found a strange behaviour while trying to complie some code with plain std::list taking a custom allocator. Consider the following code:

std::list<int, std::allocator<int>> theList;
theList.push_back(1);

It's a normal list variable with some data being added. Now if I switch it to:

std::list<int, std::allocator<int>> theList(std::allocator<int>());
theList.push_back(1);

Visual Studio 2012 fails to compile it with "error C2228: left of '.push_back' must have class/struct/union". Of course std::list has a constructor which takes a const reference to an allocator. But if i change it to:

std::list<int, std::allocator<int>> theList = std::list<int, std::allocator<int>>(std::allocator<int>());
theList.push_back(1);

all is fine. Why is the second part failing? To add to the strangeness of the situation, when trying to return theList by value:

typedef std::list<int, std::allocator<int>> TempType;

TempType func()
{
    TempType theList(std::allocator<int>());
    return theList;
}

I get "error C2664: 'std::list<_Ty,_Alloc>::list(const std::list<_Ty,Alloc> &)' : cannot convert parameter 1 from 'TempType (_cdecl *)(std::allocator<Ty> (_cdecl *)(void))' to 'const std::list<_Ty,_Alloc> &'". Looks like the compiler treats the list as a function declaration. Any idea why that could be?

2
isnt list supposed to be of one T, not two?Infested
@Infested std::list can take an allocator as the second typekrojew
I assume that in your real code, std::list<int, std::allocator<int>> is actually written as std::list<int, std::allocator<int> >? (I've not looked more in-depth; not very experienced with allocators)Dave
@Dave: neither needed nor relevant.PlasmaHH
@Dave: I have "different behaviour", because I work with compilers supporting the /current/ C++ standards as good as they can.PlasmaHH

2 Answers

5
votes

You have run into the most vexing parse. The compiler is parsing the definition of theList(std::allocator<int>()) as a function declaration. This should fix you up:

std::allocator<int> alloc;
std::list<int, std::allocator> > theList(alloc);
3
votes

It's known as the most vexing parse.

You accidentally declared a function. Adding an extra set of parenthesis will make it unambiguous.

std::list<int, std::allocator<int>> theList((std::allocator<int>()));
//                                          ^                     ^