17
votes

In the ISO International Standard for C++11, a summary of the differences between c++ 2003 and C++ 2011 is given. One of the difference is:

[diff.cpp03.special]

Change: Implicitly-declared special member functions are defined as deleted when the implicit definition would have been ill-formed.

Rationale: Improves template argument deduction failure.

Effect on original feature: A valid C++ 2003 program that uses one of these special member functions in a context where the definition is not required (e.g., in an expression that is not potentially evaluated) becomes ill-formed.

I fail to see in which condition such special functions would be ill-formed, and how it could break SFINAE. So my question boils down to:

  • Why such a change does "improves template argument deduction failure"?
  • Could you give an example?
2

2 Answers

22
votes
struct NonCopyable {
  NonCopyable() {}
private:
  NonCopyable(const NonCopyable &);
};

struct S {
  NonCopyable field;
} s;

int main() {
  return sizeof S(s);
}

Here, NonCopyable is non-copyable, but as the copy constructor is explicitly provided, no implicit copy constructor is created.

For S, no copy constructor is provided by the user, so an implicit copy constructor is created. This copy constructor would copy the NonCopyable field field, which is non-copyable, so the copy constructor would be ill-formed.

In main, the size of a copy-constructed S object is taken. This requires a copy constructor of S, but doesn't actually call it.

In C++03, this is valid. The copy constructor would be ill-formed, but since no copy is ever made, it's okay.

In C++11, this is invalid. The copy constructor is marked as deleted, so cannot be used even as the operand to sizeof.

This allows metaprogramming to detect whether the type is copyable, which was impossible in C++03.

1
votes

If you want a concrete example, std::pair is usually very easy to copy, but if one of the members is, say, a std::unique_ptr, unique_ptr doesn't allow copying from Lvalue, so it would be ill-formed: so the std::pair default Lvalue copy operations are automatically deleted.