Функция шаблона для контейнера и тип для сравнения вектора указателей - PullRequest
0 голосов
/ 07 ноября 2018

Я хочу сравнить 2 контейнера (векторы или наборы) указателей. Я пытаюсь получить функцию, которая также не зависит от типа.

Сначала я попробовал следующее. Но проблема в том, что он всегда возвращает 0, даже если оба контейнера имеют объекты с одинаковым содержимым.

  template<typename Container >
    bool isEqual(const Container &lhs,const Container &rhs ) {
        bool ok = equal(begin(lhs), end(lhs), begin(rhs));

        return ok;
    }

Затем я попытался использовать следующую функцию:

 template<typename T , typename Container >
    bool isEqual(const Container &lhs,const Container &rhs ) {
        bool ok = equal(begin(lhs), end(lhs), begin(rhs),
                    [](const T* lhs, const T* rhs){ return *lhs == * rhs; });

        return ok;
    }

но проблема в том, что он выдает следующие ошибки, и я не понимаю, почему.

 In function 'int main()':
31:31: error: no matching function for call to 'isEqual(std::vector<Point*>&, std::vector<Point*>&)'
31:31: note: candidate is:
19:6: note: template<class T, class Container> bool isEqual(const Container&, const Container&)
19:6: note:   template argument deduction/substitution failed:
31:31: note:   couldn't deduce template parameter 'T'
36:31: error: no matching function for call to 'isEqual(std::set<Point*>&, std::set<Point*>&)'
36:31: note: candidate is:
19:6: note: template<class T, class Container> bool isEqual(const Container&, const Container&)
19:6: note:   template argument deduction/substitution failed:
36:31: note:   couldn't deduce template parameter 'T'

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

using namespace std;

class Point {
    public:
    Point(int x, int y):_x(x),_y(y) {}
    private:
     int _x;
     int _y;
};

template<typename T , typename Container >
bool isEqual(const Container &lhs,const Container &rhs ) {
    bool ok = equal(begin(lhs), end(lhs), begin(rhs),
                [](const T* lhs, const T* rhs){ return *lhs == * rhs; });

    return ok;
}

int main()
{
    std::vector<Point *> v1 = {new Point(10,10)};
    std::vector<Point *> v2  = {new Point(10,10)};

    std::cout << isEqual(v1,v2) << std::endl;

    std::set<Point *> s1 = {new Point(10,10)};
    std::set<Point *> s2  = {new Point(10,10)};

    std::cout << isEqual(s1,s2) << std::endl;

    return 0;
} 

Ответы [ 2 ]

0 голосов
/ 07 ноября 2018

Поскольку вы спросили: «Я хочу сравнить 2 контейнера (векторы или наборы) указателей». Я предлагаю вам использовать следующую форму std::equal для сравнения элементов, так как ваша упомянутая форма сравнивает ее только до длины первого контейнера.

template<typename Container >
bool isEqual(const Container &lhs,const Container &rhs ) {
bool ok = equal(begin(lhs), end(lhs), begin(rhs), end(rhs),
    [](const auto* lhs, const auto* rhs){ return *lhs == * rhs; });

return ok;
}

При этом вам все равно придется определить оператор == для сравнения, которое вы выполняете в конце. Как уже упоминалось выше ответом.

0 голосов
/ 07 ноября 2018

проблема с

template<typename T , typename Container >
bool isEqual(const Container &lhs,const Container &rhs ) {
    bool ok = equal(begin(lhs), end(lhs), begin(rhs),
                [](const T* lhs, const T* rhs){ return *lhs == * rhs; });

    return ok;
}

заключается в том, что нет способа определить, что такое T. Поскольку он не используется в параметрах функции, компилятор не знает, каким он должен быть, поэтому вы должны сообщить об этом при вызове функции. Тем не менее, вам на самом деле не нужно T. Мы можем переписать лямбду, используя параметры auto, которые превратят оператор вызова функции лямбды в шаблон. Это меняет код на

template<typename Container >
bool isEqual(const Container &lhs,const Container &rhs ) {
    bool ok = equal(begin(lhs), end(lhs), begin(rhs),
                [](const auto* lhs, const auto* rhs){ return *lhs == * rhs; });

    return ok;
}

Что приводит вас к следующей проблеме. *lhs == * rhs сравнивает объекты, используя operator ==. Вы не определили operator == для Point, поэтому он не будет компилироваться. Вам нужно изменить Point на что-то вроде

class Point {
    public:
    Point(int x, int y):_x(x),_y(y) {}
    bool operator ==(const Point& rhs) { return std::tie(_x, _y) == std::tie(rhs._x, rhs._y); }
    private:
     int _x;
     int _y;
};

Значит, их действительно можно сравнить.


Обратите внимание, что если вы используете std::vector<Point> вместо std::vector<Point *>, тогда std::vector предоставляет свои operator ==, и вы можете сравнить два std::vector<Point>, просто выполнив

std::vector<Point> v1;
// fill v1
std::vector<Point> v2
// fill v2
if (v1 == v2)
    // vectors are equal.

Не похоже, что у вас есть std::vector<Point *>, поэтому я рекомендую это решение.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...