0

I am relatively new to C++11, though I have used previous versions for many years. Is this the correct way to enforce that an object will only be movable?

class CResource
{
public:
    CResource();

    CResource(CResource &&);
    CResource & operator=(CResource &&);

private:
    CResource(const CResource &) = delete;
    CResource & operator=(const CResource &) = delete;

    void * m_pResource;
};

class CAcquireResource
{
public:
    CResource && AcquireResource();
};

CResource && CAcquireResource::AcquireResource()
{
    CResource res;
    return std::move(res);
}

Edited after comments from Sebastian Redl and underscore_d

class CResource
{
public:
    CResource();
    CResource(CResource &&);
    CResource & operator=(CResource &&);
};

class CAcquireResource
{
public:
    CResource AcquireResource();
};

CResource CAcquireResource::AcquireResource()
{
    CResource res;
    return std::move(res);
}

Assertions are holding up aswell...

#include <type_traits>
#define STR_NAME(s) #s
#define STATIC_ASSERT_NOCOPYASSIGN(clazz)                                   \
    static_assert(!std::is_copy_assignable<clazz>::value,                   \
        STR_NAME(clazz) " is_copy_assignable");

#define STATIC_ASSERT_NOCOPYCONSTRUCT(clazz)                                \
    static_assert(!std::is_copy_constructible<clazz>::value,                \
        STR_NAME(clazz) " is_copy_constructible");

#define STATIC_ASSERT_MOVEASSIGN(clazz)                                     \
    static_assert(std::is_move_assignable<clazz>::value,                    \
        STR_NAME(clazz) " !is_move_assignable");

#define STATIC_ASSERT_MOVECONSTRUCT(clazz)                                  \
    static_assert(std::is_move_constructible<clazz>::value,                 \
        STR_NAME(clazz) " !is_move_constructible");

#define STATIC_ASSERT_REFERENCECLASS(clazz)                                 \
    STATIC_ASSERT_MOVEASSIGN(clazz)                                         \
    STATIC_ASSERT_MOVECONSTRUCT(clazz)                                      \
    STATIC_ASSERT_NOCOPYASSIGN(clazz)                                       \
    STATIC_ASSERT_NOCOPYCONSTRUCT(clazz)    

STATIC_ASSERT_REFERENCECLASS(CResource);

These pass with Visual Studio 2017.

nearproc
  • 35
  • 8
  • afaics: There's no point making something that is `deleted` also `private`; that just gives users another, superfluous error. See [here](https://stackoverflow.com/questions/18931133/must-a-deleted-constructor-be-private). Thinking semantically, you want the public to know that they can't use the deleted methods. – underscore_d Apr 13 '18 at 10:08
  • Thanks, thats a throw back to code I'd write when = delete didn't exist. I'll change that. I'm more concerned whether I'd enforced move only? – nearproc Apr 13 '18 at 10:09

1 Answers1

3

Your method enforces move-only.

However, the mere existence of a move constructor/assignment operator already suppresses the generation of copy constructor and assignment operator; no explicit deletion is necessary. Only a few compilers in the early days of C++11 drafts didn't correctly implement this part.

However, note that your AcquireResource code returns a reference to a local variable and thus has undefined behavior. You should return by value.

Sebastian Redl
  • 69,373
  • 8
  • 123
  • 157