[cfe-dev] Issue with map and unordered_map: call to deleted constructor of 'std::pair<const int, int>'

David Blaikie dblaikie at gmail.com
Sat Sep 17 23:09:52 PDT 2011


On Sat, Sep 17, 2011 at 7:56 PM, David Blaikie <dblaikie at gmail.com> wrote:

> I was wondering if this is a bug in the gcc 4.5.2 standard library or a bug
>>> in clang... and I'd really appreciate a work-around if anyone has one, since
>>> I'm pretty much stuck at this point.
>>
>>
>> As a baseline, this code compiles successfully when using libc++ (compile
>> with -stdlib=libc++, though you'll of course need to install libc++) & I
>> seem to have a repro of your errors with libstdc++ so I'm playing around
>> with that now.
>>
>
> I've investigated this a bit further with some help & I believe this is a
> bug in clang ToT surrounding implicit move constructor/assignment.
>

On further further investigation (& getting to what I think is the code
that's generating this - and, helpfully, quotes the standard that supports
it) I believe this is by design & libstdc++ has a bug.

The relevant portion of the standard is 12.8[class.copy] paragraph 7:

    ... If the class definition declares a move constructor or move
assignment operator, the implicitly declared copy constructor
is defined as deleted; otherwise, it is defined as defaulted. ...

libstdc++'s std::pair should be defining the move/copy ctors/assignment
operators (there's similar clauses for all these implicit definitions)
explicitly if it wants to define the move assignment operator explicitly.

[Miles: sorry about that, I'm checking your bug/repro now, but I'd hazard
it's the same thing & a bug in boost rather than clang. I'll update when
I've looked at it some more]


>
> Given this:
>
> struct foo {
>   void operator=(foo&&);
> };
>
> int main() {
>   foo g((foo()));
> }
>
>
> Clang's output is:
>
>     simple.cc:6:7: error: call to deleted constructor of 'foo'      foo g((foo()));          ^ ~~~~~~~    simple.cc:1:8: note: function has been explicitly marked deleted here    struct foo {           ^
>
> [g++ compiles this without error]
>
> Clang seems to be implementing not providing implicit move operations by
> implementing them as deleted rather than as not present. This would be
> incorrect & produces the failure above.
>
> The reason this came up in std::pair is a bit weird - it seems libstdc++'s
> std::pair has none of the big 5 (copy ctor, move ctor, copy assignment, move
> assignment, destructor) /except/ the move assignment operator. It does
> however have member function templates that, while not technically copy/move
> construction/assignment, are probably good enough for most cases. (returning
> a temporary probably should invoke the copy ctor of libstdc++'s pair,
> though, since it doesn't have a real move ctor which it should have)
>
> Anyway, the presence of the move assignment operator caused clang to
> provide a deleted move ctor rather than no move ctor at all.
>
> So there's the tale - I'll look into a fix & you'd be welcome to file a bug
> (& assign it to me, though if someone else on the list really wants to take
> it I don't mind), Matthieu. Thanks for bringing this up.
>
> [side note: we should do a better job about the warning on "The Most Vexing
> Parse" (see the declaration of 'g' in the above example which required the
> extra () to be a variable declaration instead of a function declaration) -
> like the parantheses warning I think we should have a couple of notes
> suggesting the two ways to address the issue - most likely the user actually
> meant to declare a variable & should insert the extra (). But alternatively
> they can avoid the warning by removing the extra () after the 'foo' in the
> argument list.]
>
> - David
>
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-dev/attachments/20110917/4cb5242c/attachment.html>


More information about the cfe-dev mailing list