0

New to c++ here, I'm not sure what to look up to solve this problem so I'm asking here.

I am trying to use the std::partition function to partition a list. In doing so, I make a call somewhat like this:

typename std::vector<MyType>::iterator mid = 
    std::partition(begin, end, [xval](MyType p){return p.x <= xval;});

Where begin and end are the beginning and end iterators for the list of MyType's that I want to reorder. However, when I do this, I get the following compilation error:

'MyType' has been explicitly marked deleted here
 MyType(const MyType& src) = delete;

passing argument to parameter 'p' here
    std::partition(begin, end, [xval](MyType p){return p.x <= xval;});

I've changed the type names around, but this is the long and short of it. I've done some looking around to figure out that because I made MyType non-copyable, my code is complaining because I am apparently copying it into the lambda function for partition when I write "MyType p" in those parenthesis.

My question is: How can I partition this list while not copying the arguments? I would really rather it be this list than any other (as in, I don't want to partition a list of indices if I can avoid it), because I want contiguous groups in this list to satisfy my predicate in order to make other parts of my code easier to write.

Edit: Definition of relevant part of MyType

class MyType {
public:
    ...

    MyType(const MyType& src) = delete;
    MyType& operator=(const MyType& src) = delete;
    MyType& operator=(MyType&& src) = default;
    MyType(MyType&& src) = default;

    ...
    
    float x;
}
Lavaman65
  • 863
  • 1
  • 12
  • 22
  • 1
    what is `MyType`? Can it be moved? The error is due to passing `p` by value, most likely it should be passed by reference anyhow – 463035818_is_not_an_ai Nov 08 '21 at 14:33
  • 3
    -> `[xval](const MyType& p)`? – Jarod42 Nov 08 '21 at 14:33
  • MyType is just the name of the type I am using in this partition. Like I said, I'm new to c++. What do you mean by "value" instead of by "reference"? – Lavaman65 Nov 08 '21 at 14:34
  • 1
    Does `MyType` have an overload of `std::swap`? `std::partition` calls `std::iter_swap`, which calls `std::swap(*a, *b)`. – Botje Nov 08 '21 at 14:34
  • 1
    frankly, it seems like you skipped the early chapters in your learning material. Using lambdas before passing parameters by reference can only cause confusion – 463035818_is_not_an_ai Nov 08 '21 at 14:35
  • to answer the question a [mcve] is needed. Can you show the definition of `MyType` ? – 463035818_is_not_an_ai Nov 08 '21 at 14:36
  • 3
    Forget about the parameter for the moment, and think about how you're going to reorder the vector's elements without copying them. – molbdnilo Nov 08 '21 at 14:37
  • Your objects need to at least be moveable, in order for them to be *move*d around in the vector. If you have a type that is not copyable or moveable, then you can't rearrange the order. – NathanOliver Nov 08 '21 at 14:40
  • 1
    *What do you mean by "value" instead of by "reference"?* -- This is a fundamental aspect of C++ and parameter passing. When you do this: `MyType p`, you are passing the parameter by value, meaning that an entire temporary copy is made of that value `p`. To make a copy requires the type to be copyable. If you are coming from a language such as Java, this is **not** the same thing when you specify passing in this fashion. Java uses a reference to the actual object, not so with C++. In C++, if you want to use a reference, you must explicitly state it: `MyType& p`. – PaulMcKenzie Nov 08 '21 at 14:46
  • This is all very helpful, thanks very much! I found that @Jarod42's suggestion works, I believe because my object allows copies from rvalues but not lvalues. At least, that's my current understanding. I will be sure to take 463035818_is_not_a_number's suggestion of studying more as well. I'll edit the post with more definition of MyType to allow someone who knows more to be able to explain why Jarod's answer works better. – Lavaman65 Nov 08 '21 at 14:46
  • @botje Is `std::partition` required to use a custom `swap` function? Sorting algorithms are not (relevant question: [std::sort does not always call std::swap](https://stackoverflow.com/q/14212701/580083)), but I am not sure if this issue applies also for `std::partition` itself or not. – Daniel Langr Nov 08 '21 at 14:51
  • 2
    @Lavaman65 Jarod's answer works because `[xval](MyType p)` uses pass by value, which means make a copy since the values in the vector are lvalues. You can't make a copy with your deleted copy constructor. Using `[xval](const MyType& p)` works because now you are taking a reference, meaning no copy, and then partition uses your move constructor to swap the elements in the vector. – NathanOliver Nov 08 '21 at 14:56
  • @DanielLangr `std::sort` requires elements of the sequence to be *MoveAssignable* and *MoveConstructible*, in addition to requiring the iterator be *ValueSwappable*. `std::partition` on the other hand only requires the latter, and places no requirements on the elements. I believe this means it has to be implemented in terms of `swap` or `iter_swap` alone. – Igor Tandetnik Nov 08 '21 at 17:36

0 Answers0