The problem is that the explicit std::move
prohibits copy elision, see Why does std::move prevent RVO? Another problem is that the explicit move is also unnecessary because in data create_data() { return data(); }
you are already returning an rvalue.
As a side note: A very similar question came up a while ago and it turned out that the way you are using to track object creation is very unreliable, partly because the object is empty, see RVO force compilation error on failure.
Long story short: use only the data create_data() { return data(); }
version.