C ++ - алгоритм сортировки не видит мой перегруженный оператор «<» для определенного пользователем типа.

Итак, у меня есть 1 пользовательский тип с именемfraction и он представляет собой и обычную дробь с числителем и знаменателем. Вот код:

class Fraction
{
private:
  int numerator;
  int denominator;

public:
  Fraction(int numer,int denom)
    :numerator(numer),denominator(denom){}

  int get_denom(){return denominator;}
  int get_numer(){return numerator;}
};

Как видите, он полностью реализован в заголовочном файле.

Поэтому я хочу отсортировать вектор дробей с помощью алгоритма сортировки. Вот код перегруженного & lt; & quot; оператор (примечание: он помещается в тот же файл, что и класс Fraction, но вне класса):

bool operator<(Fraction& first,Fraction& second)
{
  if(first.get_denom() == second.get_denom())
  {
    return first.get_numer()<second.get_numer()?true:false;
  }
  int first_num=first.get_denom();
  int second_num=second.get_denom();
  int lcm=(first_num*second_num)/gcd(first_num,second_num);
  int first_new_numerator=(lcm/first_num)*first.get_numer();
  int second_new_numerator=(lcm/second_num)*second.get_numer();

  return first_new_numerator<second_new_numerator?true:false;
}

Он проверяет, равны ли знаменатели, если они равны, то проверяет значения числителей. Если они не равны, он выравнивает их, используя наименьшее общее кратное и gcd.

Настоящая проблема начинается, когда я хочу использовать алгоритм сортировки в main (ошибка времени компиляции). Вот основной код:

Fraction parse_fraction(string& input)
{

  stringstream fraction_string(input);
  int numer;
  fraction_string>>numer;
  char seperator;
  fraction_string>>seperator;
  int denom;
  fraction_string>>denom;

  return Fraction(numer,denom);
}


int main()
{
  vector<Fraction> fractions;
  string input;
  while(cin>>input)
  {
    if(input=="|") break;
    fractions.push_back(parse_fraction(input));
  }

  sort(fractions.begin(),fractions.end);

  for(int i=0;i<fractions.size();i++)
  {
    cout<<fractions[i];
  }

  return 0;
}

Я получаю следующие ошибки (Примечание: у меня правильно перегружен оператор & lt; & lt; & quot; для дробей, но я не хочу вносить здесь беспорядок):

/usr/include/c++/4.6/bits/stl_algo.h||In function ‘_RandomAccessIterator std::__unguarded_partition(_RandomAccessIterator, _RandomAccessIterator, const _Tp&) [with _RandomAccessIterator = __gnu_cxx::__normal_iterator<Fraction*, std::vector<Fraction> >, _Tp = Fraction]’:|

/usr/include/c++/4.6/bits/stl_algo.h:2253|70|instantiated from ‘_RandomAccessIterator std::__unguarded_partition_pivot(_RandomAccessIterator, _RandomAccessIterator) [with _RandomAccessIterator = __gnu_cxx::__normal_iterator<Fraction*, std::vector<Fraction> >]’|

/usr/include/c++/4.6/bits/stl_algo.h:2284|54|instantiated from ‘void std::__introsort_loop(_RandomAccessIterator, _RandomAccessIterator, _Size) [with _RandomAccessIterator = __gnu_cxx::__normal_iterator<Fraction*, std::vector<Fraction> >, _Size = long int]’|

/usr/include/c++/4.6/bits/stl_algo.h:5330|4|instantiated from ‘void std::sort(_RAIter, _RAIter) [with _RAIter = __gnu_cxx::__normal_iterator<Fraction*, std::vector<Fraction> >]’|

/home/vanio/Desktop/workspace/C++/Ordner/main.cpp:35|43|instantiated from here|

/usr/include/c++/4.6/bits/stl_algo.h|2212|error: no match for ‘operator<’ in ‘__first.__gnu_cxx::__normal_iterator<_Iterator, _Container>::operator* [with _Iterator = Fraction*, _Container = std::vector<Fraction>, __gnu_cxx::__normal_iterator<_Iterator, _Container>::reference = Fraction&]() < __pivot’|

/usr/include/c++/4.6/bits/stl_algo.h|2212|note: candidates are:|

/usr/include/c++/4.6/bits/stl_pair.h|207|note: template<class _T1, class _T2> bool std::operator<(const std::pair<_T1, _T2>&, const std::pair<_T1, _T2>&)|

/usr/include/c++/4.6/bits/stl_iterator.h|291|note: template<class _Iterator> bool std::operator<(const std::reverse_iterator<_Iterator>&, const std::reverse_iterator<_Iterator>&)|

/usr/include/c++/4.6/bits/stl_iterator.h|341|note: template<class _IteratorL, class _IteratorR> bool std::operator<(const std::reverse_iterator<_IteratorL>&, const std::reverse_iterator<_IteratorR>&)|

/usr/include/c++/4.6/bits/basic_string.h|2510|note: template<class _CharT, class _Traits, class _Alloc> bool std::operator<(const std::basic_string<_CharT, _Traits, _Alloc>&, const std::basic_string<_CharT, _Traits, _Alloc>&)|

/usr/include/c++/4.6/bits/basic_string.h|2522|note: template<class _CharT, class _Traits, class _Alloc> bool std::operator<(const std::basic_string<_CharT, _Traits, _Alloc>&, const _CharT*)|

/usr/include/c++/4.6/bits/basic_string.h|2534|note: template<class _CharT, class _Traits, class _Alloc> bool std::operator<(const _CharT*, const std::basic_string<_CharT, _Traits, _Alloc>&)|

/usr/include/c++/4.6/bits/stl_vector.h|1290|note: template<class _Tp, class _Alloc> bool std::operator<(const std::vector<_Tp, _Alloc>&, const std::vector<_Tp, _Alloc>&)|

/home/vanio/Desktop/workspace/C++/Ordner/Fraction.h|39|note: bool operator<(Fraction&, Fraction&)|

/home/vanio/Desktop/workspace/C++/Ordner/Fraction.h|39|note:   no known conversion for argument 2 from ‘const Fraction’ to ‘Fraction&’|

/usr/include/c++/4.6/bits/stl_algo.h|2215|error: no match for ‘operator<’ in ‘__pivot < __last.__gnu_cxx::__normal_iterator<_Iterator, _Container>::operator* [with _Iterator = Fraction*, _Container = std::vector<Fraction>, __gnu_cxx::__normal_iterator<_Iterator, _Container>::reference = Fraction&]()’|

/usr/include/c++/4.6/bits/stl_algo.h|2215|note: candidates are:|

/usr/include/c++/4.6/bits/stl_pair.h|207|note: template<class _T1, class _T2> bool std::operator<(const std::pair<_T1, _T2>&, const std::pair<_T1, _T2>&)|

/usr/include/c++/4.6/bits/stl_iterator.h|291|note: template<class _Iterator> bool std::operator<(const std::reverse_iterator<_Iterator>&, const std::reverse_iterator<_Iterator>&)|

/usr/include/c++/4.6/bits/stl_iterator.h|341|note: template<class _IteratorL, class _IteratorR> bool std::operator<(const std::reverse_iterator<_IteratorL>&, const std::reverse_iterator<_IteratorR>&)|

/usr/include/c++/4.6/bits/basic_string.h|2510|note: template<class _CharT, class _Traits, class _Alloc> bool std::operator<(const std::basic_string<_CharT, _Traits, _Alloc>&, const std::basic_string<_CharT, _Traits, _Alloc>&)|

/usr/include/c++/4.6/bits/basic_string.h|2522|note: template<class _CharT, class _Traits, class _Alloc> bool std::operator<(const std::basic_string<_CharT, _Traits, _Alloc>&, const _CharT*)|

/usr/include/c++/4.6/bits/basic_string.h|2534|note: template<class _CharT, class _Traits, class _Alloc> bool std::operator<(const _CharT*, const std::basic_string<_CharT, _Traits, _Alloc>&)|

/usr/include/c++/4.6/bits/stl_vector.h|1290|note: template<class _Tp, class _Alloc> bool std::operator<(const std::vector<_Tp, _Alloc>&, const std::vector<_Tp, _Alloc>&)|

/home/vanio/Desktop/workspace/C++/Ordner/Fraction.h|39|note: bool operator<(Fraction&, Fraction&)|

/home/vanio/Desktop/workspace/C++/Ordner/Fraction.h|39|note:   no known conversion for argument 1 from ‘const Fraction’ to ‘Fraction&’|
||=== Build finished: 22 errors, 0 warnings ===|
 Thomas Matthews31 июл. 2012 г., 02:21
Вы должны определить параметры дляoperator< какconst Рекомендации.
 Thomas Matthews31 июл. 2012 г., 02:23
Нет причин использовать...? true : false в вашемoperator< функция. Компилятор должен быть в состоянии преобразовать выражение в bool. Оставь это какreturn first_new_numerator<second_new_numerator;
 aschepler31 июл. 2012 г., 02:24
Это противоположно обычному, но в этом случае последнее сообщение об ошибке является важным.
 TheSteve31 июл. 2012 г., 02:19
Что произойдет, если вы сделаете оператора членом класса?bool operator < (Fraction & second)
 Andrew Lazarus31 июл. 2012 г., 02:21
Два предложения стиля кодирования.First: вместоreturn a?true:false простоreturn a. Second: gcd убивает муху из пушки для этой проблемы (и медленно). Просто умножьте на оба знаменателя. Вы можете даже пропустить проверку, равны ли знаменатели, что, вероятно, стоит больше циклов ЦП, чем стоит.

Ответы на вопрос(2)

Решение Вопроса
bool operator<(Fraction& first,Fraction& second)

Проблема в том, что ваша перегрузкаoperator< принимает только неконстантные аргументы, но алгоритм пытается сравнить постоянную ссылку сFraction с элементами в вашем контейнере.

посколькуoperator< не изменяет содержимое сравниваемых объектов, оно должно принимать их по ссылке const:

bool operator<(Fraction const & first,Fraction const & second)
 31 июл. 2012 г., 13:40
@XanderTulip: Это точные эквиваленты, и вопрос о том, является ли один из них более читабельным, чем другой, подлежит обсуждению.
 Vanio Begic31 июл. 2012 г., 02:45
Спасибо, это и постер под это
 31 июл. 2012 г., 06:31
Более распространенная и читаемая версия: оператор bool & lt; (const Fraction & amp; first, const Fraction & amp; second);

Рассмотрим этот код:

Fraction a, b;
bool res = (a < b);

Вторая строка - это вызов

bool res = a.operator<(b);
As suggested above - being const correct is going to serve you very well in a long run Define a member bool operator<(const Fraction&) const to make the sorting implementation happy or just go with the first suggestion above - be const-correct with bool operator<(const Fraction& a, const Fraction& b)
 Vanio Begic31 июл. 2012 г., 02:45
Спасибо, это и постер выше решили это
 31 июл. 2012 г., 04:04
В этом конкретном случаеoperator< реализован как свободная функция, поэтому преобразование будетbool res = operator<( a, b );, Кроме того, чаще всего лучше реализовывать бинарные операторы как свободные функции, а не функции-члены, обеспечивая симметрию относительно типов (никакие преобразования не могут вызывать функцию-член)

Ваш ответ на вопрос