7

I have a class Data which is (as for now) non-copyable. std::sort on std::vector<Data> works because I have defined move-constructor and move-assignment for Data. I do it this way because the class has a lot of data inside and copying the contents would be too slow. However, I am considering now adding a copy constructor Data(const Data& other) and standard assignment operator (from const Data&) to the class, for unrelated reasons. How can I make sure that when I sort a vector of Data, std::sort will still use the move-constructor and move-assignment?

quant_dev
  • 6,181
  • 1
  • 34
  • 57
  • 2
    Did you try it? You might be surprised at the results. – Sam Varshavchik Jan 10 '16 at 00:03
  • 1
    See also: http://stackoverflow.com/questions/14212701/stdsort-does-not-always-call-stdswap – Sam Varshavchik Jan 10 '16 at 00:20
  • 5
    If you do make the class copyable and moveable both, you should declare the move constructor `noexcept` (assuming it is). Doesn't affect `sort` performance, but it will make a difference when adding elements to the `vector` because of its strong exception guarantee. – Praetorian Jan 10 '16 at 00:44
  • @Praetorian If class `T` has a `noexcept` move constructor, will `std::vector` have a `noexcept` move constructor too? – quant_dev Jan 10 '16 at 00:48
  • 3
    @quant_dev: Those are not related. Vector's move constructor moves its buffer, not individual T instances (note: the small buffer optimization is not valid for std::vector). – Cheers and hth. - Alf Jan 10 '16 at 00:50
  • 1
    "How can I make sure": just for a test, you can add `throw` or `abort` to your copy constructor/assignment and check that sorting does not hit it. Or you can declare **but not define** them and check that it still links. Keeping tests for it long term, when you will actually be using copies in other parts of the code, seems painful and unnecessary. – Marc Glisse Jan 10 '16 at 08:00
  • I ended up not declaring them and adding a `copy` function, to make it clear that normally the `Data` objects are moved, not copied. – quant_dev Jan 11 '16 at 07:56

2 Answers2

4

How can I make sure that when I sort a vector of Data, std::sort will still use the move-constructor and move-assignment?

Actually, you don't need to. You have to make sure that the swap function used exploits directly or indirectly any trick already used in the move constructor. That is I think how it works. In other words, sort needs a good swap, not necessarily a copy.

Where "directly" could mean simply using the default std::swap that uses the move constructor when it can.

template <class T> void swap (T& a, T& b)
{
  T c(std::move(a)); a=std::move(b); b=std::move(c);
}

So, chances are, you don't need to do anything special because swap (or as @MarcGlisse noted, the sort algorithm directly) will use the move constructor.

alfC
  • 14,261
  • 4
  • 67
  • 118
  • 3
    `sort` is not specified to use only `swap`. If you look at actual implementations, they also use move constructors and move assignments. – Marc Glisse Jan 10 '16 at 07:57
  • 1
    @MarcGlisse, probably right and depends on the implementation I guess. In either case the OP shouldn't worry. – alfC Jan 10 '16 at 08:06
3

Just provide move-constructor, move-assignment and free swap-function (in the same namespace) for your Data class

Victor Dyachenko
  • 1,363
  • 8
  • 18