4

I have made a member of a class non-copyable but I have given it a move constructor and assignment operator. Yet it dosn't play ball with a container like a vector.

class NonCopyable
{
public:
    NonCopyable(const NonCopyable&) = delete;
    NonCopyable& operator=(const NonCopyable&) = delete;


protected:
    NonCopyable()
    {
    }

    ~NonCopyable() _NOEXCEPT
    {
    }
};


class Member : NonCopyable
{
public:
    Member(int i) : mNum(i)
    {
    }
    ~Member()
    {
    }

    Member(Member&& other) _NOEXCEPT : mNum(other.mNum)
    {
    }

    Member& operator= (Member&& other) _NOEXCEPT
    {
        std::swap(mNum, other.mNum);
        return *this;
    }

private:
    int mNum;
};


struct Item
{
    Item(int i) : mMember(i)
    {
    }

    Member mMember;
};



int _tmain(int argc, _TCHAR* argv[])
{
    std::vector<Item> vec;
    vec.emplace_back(1);

    return 0;
}

The following compiler error:

error C2280: 'NonCopyable::NonCopyable(const NonCopyable &)' : attempting to reference a deleted function
see declaration of 'NonCopyable::NonCopyable'
This diagnostic occurred in the compiler generated function 'Member::Member(const Member &)'

Why dosn't the compiler recognize the Member can be moved? What am I missing?

EDIT: Visual studio 2013

EDIT2: I add this to Item and it compiles:

Item(Item&& other) _NOEXCEPT : mMember(std::move(other.mMember))
{
}

Am I OK? Is that it?

KaiserJohaan
  • 9,028
  • 20
  • 112
  • 199
  • Also works on clang. Most likely Microsoft not being very far with implementing recent standards again. – Baum mit Augen May 31 '15 at 19:36
  • 2
    works fine on VS2015 but doesn't on VS2013 – doqtor May 31 '15 at 19:40
  • 2
    VS2013 does not create special move member functions for you. Therefore, `Item` won't have a neither a move ctor nor a move assignment operator. – dyp May 31 '15 at 19:51
  • 1
    Don't use `_NOEXCEPT` in your own code, that's meant to be a private identifier for the MSVC stdlib implementation. There's no guarantee it'll exist in a newer version, and could even expand to something other than `throw()` or `noexcept`. Either [define your own macro](https://stackoverflow.com/a/18387764/241631) or let [someone else](http://www.boost.org/doc/libs/release/libs/config/doc/html/boost_config/boost_macro_reference.html) do the hard work (you want `BOOST_NOEXCEPT_OR_NOTHROW`) – Praetorian May 31 '15 at 20:16
  • VS2015 fixes this bug. – Yakk - Adam Nevraumont Jun 01 '15 at 02:04

1 Answers1

2

In VS2013 default and deleted functions and rvalue references are partially implemented. Upgrade to VS2015 where these feature according to Microsoft are fully implemented (your example compiles fine). C++11/14/17 Features In VS 2015 RC

doqtor
  • 8,414
  • 2
  • 20
  • 36
  • 2
    It's not just that defaulted functions are implemented incompletely. The move ctor that should be implicitly be declared for `Item` in the OP isn't even declared by MSVC. It isn't implicitly defined as defaulted either, but that's not causing the error in the OP. – dyp May 31 '15 at 19:54
  • @dyp I've updated the answer to mention about rvalue references too. – doqtor May 31 '15 at 21:13
  • I never liked the usage of the term "rvalue references" when referring to *move special member functions*. VS supports *rvalue references* as types and within expressions since VS2010, it just doesn't implicitly declare move ctors / move assignment operators. Nevertheless, it's used not just by MSVC but also other major compiler implementers implying move special member functions when talking about C++11 support :( – dyp May 31 '15 at 21:22