#ifndef NON_COPYABLE_H
#define NON_COPYABLE_H


/// XXX: Not sure but maybe there is a C++11 std::non_copyable that does the same as this
/// Actually C++11 has the additional ability to add '= delete' to a member to say it can be used.

#ifdef HAVE_CPP11
#  define DELETE      = delete
#else
#  define DELETE
#endif


/// This way has the advantage of not adding to the size of the base class if that is important [1]
/// [1] Ref: http://trac.webkit.org/changeset/68414
#define MAKE_NONCOPYABLE(ClassName) \
    private: \
        ClassName(const ClassName&) DELETE; \
        ClassName& operator=(const ClassName&) DELETE; \


/* Utility classes */
struct NoCopy
{
public:
    NoCopy() {}
private:
    NoCopy(const NoCopy &) DELETE;
};

struct NoAssign
{
private:
    NoAssign &operator=(const NoAssign &) DELETE;
};

struct NonInstantiable
{
private:
    NonInstantiable() DELETE;
};

struct NoCopyAssign : NoCopy, NoAssign
{
};

typedef NoCopyAssign NoAssignCopy;

// Not tested
struct NoMove
{
public:
    NoMove() {}
private:
    NoMove(const NoMove &&) DELETE;
};

struct NoMoveCopyAssign : NoMove, NoCopy, NoAssign
{
};


///
/// Make classes NonCopyable
///
/// Making a class NonCopyable means preventing objects of the class being copied. This is useful if
/// the class manages a resource that can only be held by one object such that it can't be reference
/// counted, or it is the underlying object that becomes reference counted. Idea from here [1].
///
/// [1] Ref: http://stackoverflow.com/questions/9458741/with-explicitly-deleted-member-functions-in-c11-is-it-still-worthwhile-to-inh
///
class NonCopyable
{
public:
	NonCopyable() {}
private:
	NonCopyable(NonCopyable const &);
	NonCopyable& operator=(NonCopyable const &);
};


/*

	Example usage:

	class MyNonCopyableClass : private NonCopyable
	{
		public:
			MyNonCopyableClass() {}
	};

    MyNonCopyableClass create()
    {
        MyNonCopyableClass var;
        return var;
    }

	Now it is not possible to copy objects of this type without a compiler error:

    void function()
	{
        MyNonCopyableClass obj1;
        MyNonCopyableClass obj2;
        MyNonCopyableClass obj3 = create(); // Allowed due to move semantics in c++11, use NoMoveCopyAssign to prevent

		// These attempts to make a copy of obj1 will cause a compiler error
		MyNonCopyableClass obj3(obj1);
		obj2 = obj1;
	}

*/


#endif // NON_COPYABLE_H
