Home > Mobile >  `std::remove` in template function causing problems with `vector.begin()` being `const`
`std::remove` in template function causing problems with `vector.begin()` being `const`

Time:04-11

The error message: "binary '==': no operator found which takes a left-hand operand of type 'const _Ty' (or there is no acceptable conversion)"

The error seems to be because I'm giving std::remove a const value for the first argument, but I don't see exactly how v.begin() being unmodifiable would cause problems, nor why this error only occurs if the type of the vector is templated, as opposed to a known type vector.

The template function:

// Erases a every element of a certain value from a vector
template <typename T>
std::vector<T> eraseElement(std::vector<T> v, T elem)
{
    typename std::vector<T>::iterator newEnd = std::remove(v.begin(), v.end(), elem);
    v.erase(newEnd, v.end());
    return v;
}

An example of the way I'm calling the template function:

struct exampleStruct
{
    int x;
}

std::vector<exampleStruct> v;
exampleStruct elem;
elem.x = 2451;
v.push_back(elem);

v = eraseElement(v, elem);

CodePudding user response:

nor why this error only occurs if the type of the vector is templated, as opposed to a known type vector.

It also occurs if you substitute exampleStruct manually.

std::vector<exampleStruct> eraseElement(std::vector<exampleStruct> v, exampleStruct elem)
{
    auto newEnd = std::remove(v.begin(), v.end(), elem);
    v.erase(newEnd, v.end());
    return v;
}

That's because there isn't an operator== for exampleStruct. You probably want something like

bool operator==(const exampleStruct & lhs, const exampleStruct & rhs)
{
    return lhs.x == rhs.x;
}

or with a C 20 implementation

struct exampleStruct 
{
    int x;
    friend bool operator==(const exampleStruct &, const exampleStruct &) = default;
};

CodePudding user response:

The error message: "binary '==': no operator found which takes a left-hand operand of type 'const _Ty' (or there is no acceptable conversion)"

The error seems to be because I'm giving std::remove a const value for the first argument

Probably not. The error is because you're probably using T that is not equality comparable (in other words, there is no equality operator - which is the binary operator== - that would accept the operands). Constness should not be a problem because an equality comparable type should accept const arguments for comparison.

exampleStruct in particular is not equality comparable. One way to solve your problem is to make it equality comparable. You can do that by defining the binary operator== for the type. I recommend following approach:

struct exampleStruct
{
    int x;
    friend auto operator<=>(const exampleStruct&, const exampleStruct&) = default;
};

Another way to solve the problem is to not use std::remove, but to use std::remove_if instead. That way you can provide the condition to remove the element which doesn't have to compare the elements for their equality.

nor why this error only occurs if the type of the vector is templated, as opposed to a known type vector.

I highly doubt this. exampleStruct remains non-comparable whether eraseElement is a template or not.

  • Related