Use the following syntax to specify how functions should be handled:
- To default a function, use =default instead of the function body. Only special class member functions that have defaults can be defaulted:
struct foo
{
foo() = default;
};
- To delete a function, use =delete instead of the function body. Any function, including non-member functions, can be deleted:
struct foo
{
foo(foo const &) = delete;
};
void func(int) = delete;
Use defaulted and deleted functions to achieve various design goals, such as the following examples:
- To implement a class that is not copyable, and implicitly not movable, declare the copy operations as deleted:
class foo_not_copyable
{
public:
foo_not_copyable() = default;
foo_not_copyable(foo_not_copyable const &) = delete;
foo_not_copyable& operator=(foo_not_copyable const&) = delete;
};
- To implement a class that is not copyable, but is movable, declare the copy operations as deleted and explicitly implement the move operations (and provide any additional constructors that are needed):
class data_wrapper
{
Data* data;
public:
data_wrapper(Data* d = nullptr) : data(d) {}
~data_wrapper() { delete data; }
data_wrapper(data_wrapper const&) = delete;
data_wrapper& operator=(data_wrapper const &) = delete;
data_wrapper(data_wrapper&& o) :data(std::move(o.data))
{
o.data = nullptr;
}
data_wrapper& operator=(data_wrapper&& o)
{
if (this != &o)
{
delete data;
data = std::move(o.data);
o.data = nullptr;
}
return *this;
}
};
- To ensure a function is called only with objects of a specific type, and perhaps prevent type promotion, provide deleted overloads for the function (the following example with free functions can also be applied to any class member functions):
template <typename T>
void run(T val) = delete;
void run(long val) {} // can only be called with long integers