Войти
ПрограммированиеФорумГрафика

Сравнение std::vector<SomePOD>

Страницы: 1 2 Следующая »
#0
16:04, 26 окт. 2018

Имеется некий внешний pod-класс, назовём его SomePOD. Для него не определён оператор сравнения, определяю:

bool operator < (const SomePOD &left, const SomePOD &right)
{
  return std::tie(left.a, left.b, left.c) < std::tie(right.a, right.b, right.c);
}
далее есть два вектора из таких классов:
std::vector<SomePOD> a, b;
хочется их сравнить:
bool res = a < b;
в принципе для векторов определён оператор сравнения. однако, почему-то даже с определённым оператором сравнения для типа элементов векторов, сами вектора не сравниваются, выплёвывая нечитаемый поток ошибок, начинающийся с
...\include\xutility(1062): error C2672: 'operator __surrogate_func': no matching overloaded function found

Производительность не интересует совершенно. Хочется понять, почему не работает.

#1
16:11, 26 окт. 2018

Suslik
== определил?

#2
(Правка: 16:16) 16:14, 26 окт. 2018

== не нужен, нужен именно <

ещё поплюхался. оказалось, что проблема в неймспейсе. полный код проблемного кода:

namespace test
{
  struct SomePOD
  {
    int a;
  };
}
bool operator < (const test::SomePOD& left, const test::SomePOD& right)
{
  return left.a < right.a;
}
int main()
{
  std::vector<test::SomePOD> a, b;
  bool res = a < b;
}
особенность в том, что код компилится, если объявление operator <  затолкать внутрь неймспейса test. но этот неймспейс как бы — вообще не мой, я не хочу в нём оператор определять. почему так получается?

#3
16:30, 26 окт. 2018

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

#4
16:54, 26 окт. 2018

Suslik
А если объявлять оператор сравнения в самом классе?

#5
17:08, 26 окт. 2018

думаю там стоит проверка что тип имеет оператор сравнения, а так как это глобальный оператор в другом неймспейсе, то проверка не срабатывает

#6
17:10, 26 окт. 2018

VoidSpirit
> А если объявлять оператор сравнения в самом классе?
В классе вектора?

#7
(Правка: 17:22) 17:19, 26 окт. 2018

Great V.
> В классе вектора?
В классе SomePOD.
Хотя, увидел что он внешний... Значит, можно вывести потомка, в котором определить только оператор сравнения

#8
18:49, 26 окт. 2018

Suslik
> хочется их сравнить
Если хочется только этого, то можно тупо

  bool res = std::lexicographical_compare(
      a.begin(),a.end(),
      b.begin(),b.end(),
      [](const test::SomePOD &left,const  test::SomePOD &right)->bool
      {
          return left.a < right.a;
      });
Если же
> Хочется понять, почему не работает.
тогда интереснее.

Влобный

  test::SomePOD x,y;
  bool res = x<y;
рядом работает.

Насколько я понимаю - потому что он (оператор "меньше") зовётся из глобального пространства имён, а в коде сравнивающем векторы - изнутри std, и https://en.cppreference.com/w/cpp/language/adl отрабатывает по-разному.

#9
19:47, 26 окт. 2018

гцц говорит:

/usr/include/c++/5/bits/predefined_ops.h:43:23: error: no match for ‘operator<’ (operand types are ‘const test::SomePOD’ and ‘const test::SomePOD’)
      { return *__it1 < *__it2; }

Так что, должно быть, это таки особенности ADL.

#10
(Правка: 20:29) 20:21, 26 окт. 2018

FordPerfect
> и https://en.cppreference.com/w/cpp/language/adl отрабатывает по-разному.
очень странная фигня:
https://ideone.com/zchKUL

я бы запретил такое.

upd:
счастливой отладки:
https://ideone.com/ydCdrR

#11
5:37, 27 окт. 2018

Всё так. Иначе operator+ для std::string будет работать только когда using namespace std;

#12
13:50, 29 окт. 2018

Adler
> очень странная фигня:
> https://ideone.com/zchKUL
> я бы запретил такое.

Wraith
> Всё так. Иначе operator+ для std::string будет работать только когда using
> namespace std;

В крестах много чего сделано через задницу.
В Ü я сделал более грамотно:
никакого неявного выбора пространства для функции по аргументам нету, для функций действует то же правило, что и для других имён. А чтобы всякие std::string::operator+ работали, для операторов сделана отдельная логика - оператор должен быть определён в одном из классов аргументов.

#13
14:04, 29 окт. 2018

Panzerschrek[CN]
> оператор должен быть определён в одном из классов аргументов
А что если есть два чужих класса (например Vector2 и Size2) которые разработчик жутко хочет складывать и вычитать, но в чужой либе это не предусмотрено?

#14
(Правка: 16:39) 16:38, 29 окт. 2018

mahrizh
> А что если есть два чужих класса (например Vector2 и Size2) которые разработчик
> жутко хочет складывать и вычитать, но в чужой либе это не предусмотрено?

#include "Vector2.h"
Vector2.source_code+="Vector2 operator+(Vector2&ref){/*...*/}";
Страницы: 1 2 Следующая »
ПрограммированиеФорумГрафика