Home > OS >  std::unique not working as expected with struct
std::unique not working as expected with struct

Time:02-24

I'm currently working on a 2D game in c where the level is defined by edges:

struct Edge
{
    vec2int start;
    vec2int end;
}

The struct vec2int is a vector with x, y coordinates and has all needed operators (in this particular case operator==) overloaded. Because of a data structure that stores the edges inside of a grid, there can be duplicate edges in different cells inside the grid. When combining them back into a single std::vector I tried to get rid of them like this:

auto it = std::unique(
    edges.begin(),
    edges.end(),
    [&](const Edge& e1, const Edge& e2)
    {
        return e1.start == e2.start && e1.end == e2.end;
    });

edges.resize(std::distance(edges.begin(), it));

For whatever reason this deletes only a few (or none) of the duplicate edges. I have no idea why. Is there something I am missing about std::unique?

Thanks in advanced!

I hope this counts as a minimal reproducible example:

#include <algorithm>
#include <iostream>
#include <vector>

template<class T>
struct v2d_generic
{
    T x = 0;
    T y = 0;
    
    bool operator==(const v2d_generic& rhs) const
    {
        return (this->x == rhs.x && this->y == rhs.y);
    }
    bool operator!=(const v2d_generic& rhs) const
    {
        return (this->x != rhs.x || this->y != rhs.y);
    }
};

typedef v2d_generic<int> vec2i;

struct Edge
{
    vec2i start;
    vec2i end;
};


int main(void)
{
    std::vector<Edge> edges;

    edges.push_back(Edge{vec2i{1, 1}, vec2i{1, 1}});
    edges.push_back(Edge{vec2i{1, 1}, vec2i{1, 2}});
    edges.push_back(Edge{vec2i{1, 1}, vec2i{1, 1}});
    edges.push_back(Edge{vec2i{1, 1}, vec2i{1, 2}});

    std::cout << edges.size() << std::endl;

    auto it = std::unique(
        edges.begin(),
        edges.end(),
        [&](const Edge& e1, const Edge& e2)
        {
            return e1.start == e2.start && e1.end == e2.end;
        });

    edges.resize(std::distance(edges.begin(), it));

    std::cout << edges.size() << std::endl;
}

This outputs 4 both times

CodePudding user response:

std::unique removes consecutive equivalent elements. In your example, you do not have consecutive equal elements, so it should not remove anything.

If you do not care about the order of the elements in your range, you can sort it before calling std::unique.

  • Related