Here are four ways to make class non-copyable:
#include <stdio.h>
#include <type_traits>
class A {
public:
A(const A&) = delete;
void operator=(const A&) = delete;
};
class B {
private:
B(const B&) = delete;
void operator=(const B&) = delete;
};
class C {
public:
C(const C&) = delete;
void operator=(const C&) = delete;
void operator=(C) = delete;
};
class D {
private:
D(const D&) = delete;
void operator=(const D&) = delete;
void operator=(D) = delete;
};
int main() {
printf("%d %d\n", std::is_copy_constructible<A>::value, std::is_copy_assignable<A>::value);
printf("%d %d\n", std::is_copy_constructible<B>::value, std::is_copy_assignable<B>::value);
printf("%d %d\n", std::is_copy_constructible<C>::value, std::is_copy_assignable<C>::value);
printf("%d %d\n", std::is_copy_constructible<D>::value, std::is_copy_assignable<D>::value);
}
On MSVC2013 x64 (18.00.40629 for x64
), it prints:
1 1 //A
0 1 //B
1 0 //C
0 0 //D
On a proper compiler, all eight values must be zeroes.
Unfortunately, this does not provide a good way to workaround the bug in MSVC2013, even for your own classes. Because if you declare assignment operator accepting argument by value, then you cannot declare move assignment in the same class (any move assignment will not compile due to ambiguous overload).
P.S. The key idea for fixing assignment was taken from this related answer.