Компараторы
От: dlyas  
Дата: 24.11.11 21:43
Оценка:
Здравствуйте!
Я не очень знаю С++ и прошу помочь как новичку.

Вот есть std::sort, у него есть параметр — предикат сравнения. То есть компаратор. Теперь пусть я написал этот компаратор в каком-то виде. Но теперь пишу функцию вида std::sort, пусть даже свой sort.
Как объявить эту функцию, как показать, что она принимает компаратор? Быть может где-то можно прочитать конкретный пример? Но будет куда лучше, если кто-нибудь приведет его здесь. Потому что все, что я нахожу про компараторы — это как их использовать.

И еще вопрос. Пусть у меня есть структура my_struct.
Я могу написать:

std::sort (begin, end, std::less<my_struct>);

? и что это будет значить? Как мне этот less переопределить.

Извиняюсь, если вопросы очень глупы.
Re: Компараторы
От: о_О
Дата: 24.11.11 23:05
Оценка: +1
Что мешает открыть <algorithm> и посмотреть как сделаны std::sort и std::less?
Re: Компараторы
От: Marty Пират https://www.youtube.com/channel/UChp5PpQ6T4-93HbNF-8vSYg
Дата: 25.11.11 01:27
Оценка:
Здравствуйте, dlyas, Вы писали:

D>Здравствуйте!

D>Я не очень знаю С++ и прошу помочь как новичку.

D>Вот есть std::sort, у него есть параметр — предикат сравнения. То есть компаратор. Теперь пусть я написал этот компаратор в каком-то виде. Но теперь пишу функцию вида std::sort, пусть даже свой sort.

D>Как объявить эту функцию, как показать, что она принимает компаратор? Быть может где-то можно прочитать конкретный пример? Но будет куда лучше, если кто-нибудь приведет его здесь. Потому что все, что я нахожу про компараторы — это как их использовать.

D>И еще вопрос. Пусть у меня есть структура my_struct.

D>Я могу написать:

D>
D>std::sort (begin, end, std::less<my_struct>);
D>

D>? и что это будет значить? Как мне этот less переопределить.

std::less вроде использует оператор operator<, соответственно, надо его определить для структуры.
Если сортировка производится по критерию, отличному от логики operator<, то определяем свою функцию или функтор сравнения:

struct my_struct_less
{
bool operator()( const my_struct& s1, const my_struct &s2)
   {
    // тут сравниваем как надо
   }
};


Вообще, my_struct_less вроде надо наследовать от std::binary_predicate, но я не помню, зачем, и не делаю так. Вроде работает.
Маньяк Робокряк колесит по городу
Re[2]: Компараторы
От: Marty Пират https://www.youtube.com/channel/UChp5PpQ6T4-93HbNF-8vSYg
Дата: 25.11.11 01:42
Оценка:
Здравствуйте, Marty, Вы писали:

Забыл, лучше так
bool operator()( const my_struct& s1, const my_struct &s2) const
Маньяк Робокряк колесит по городу
Re: Компараторы
От: MasterZiv СССР  
Дата: 25.11.11 08:40
Оценка:
On 11/25/2011 01:43 AM, dlyas wrote:

> компаратор. Теперь пусть я написал этот компаратор в каком-то виде. Но теперь

> пишу функцию вида std::sort, пусть даже свой sort.
> Как объявить эту функцию, как показать, что она принимает компаратор?

Если пишешь на шаблонах, то НИКАК.
Надо её просто объявить как какой-то параметр шаблона -- тип, и вызвать, и всё.

Быть может
> где-то можно прочитать конкретный пример? Но будет куда лучше, если кто-нибудь
> приведет его здесь. Потому что все, что я нахожу про компараторы — это как их
> использовать.

Код стандартного std::sort смотри, и всё.

> std::sort (begin, end, std::less<my_struct>);

> ? и что это будет значить? Как мне этот less переопределить.

Тебе надо определить operator == и operator < для этого типа my_struct.
Posted via RSDN NNTP Server 2.1 beta
Re[3]: Компараторы
От: MasterZiv СССР  
Дата: 25.11.11 08:43
Оценка:
On 11/25/2011 05:42 AM, Marty wrote:

> bool operator()(const my_struct& s1,const my_struct&s2)*const*


Это делать не надо, есть уже стандартный less. Но можно.
И ты всё перепутал. Если делать operator() для изображения из него LESS
для этого твоего типа, то это должен быть отдельный класс, не в my_struct.
Можно конечно в my_struct сделать статическую функцию, но опять-таки
это не то, что ты написал.

Нужно просто в my_struct определить operator < и operator ==
Posted via RSDN NNTP Server 2.1 beta
Re[2]: Компараторы
От: о_О
Дата: 25.11.11 08:59
Оценка:
Здравствуйте, Marty, Вы писали:

M>Вообще, my_struct_less вроде надо наследовать от std::binary_predicate

не знаю таких. знаю std::binary_function

M>но я не помню, зачем, и не делаю так. Вроде работает.

с std::bind работать не будет
Re[4]: Компараторы
От: Marty Пират https://www.youtube.com/channel/UChp5PpQ6T4-93HbNF-8vSYg
Дата: 25.11.11 08:59
Оценка:
Здравствуйте, MasterZiv, Вы писали:

>> bool operator()(const my_struct& s1,const my_struct&s2)*const*


MZ>Это делать не надо, есть уже стандартный less. Но можно.

MZ>И ты всё перепутал. Если делать operator() для изображения из него LESS
Не-не-не, это ты все перепутал
Я так и написал, что хватит оператора <, а если нужна сортировка по какому-то иному критерию, чем operator< или operator>, то пишем компаратор.
MZ>для этого твоего типа, то это должен быть отдельный класс, не в my_struct.
Я так и написал, мой компаратор зовется my_struct_less.

MZ>Можно конечно в my_struct сделать статическую функцию, но опять-таки

MZ>это не то, что ты написал.

MZ>Нужно просто в my_struct определить operator < и operator ==

Про == забыл (или не знал). А он точно нужен? Там вроде в sort'е используются сравнения cmp(s1,s2) и cmp(s2,s1)
Маньяк Робокряк колесит по городу
Re[3]: Компараторы
От: Marty Пират https://www.youtube.com/channel/UChp5PpQ6T4-93HbNF-8vSYg
Дата: 25.11.11 09:01
Оценка:
Здравствуйте, о_О, Вы писали:

M>>но я не помню, зачем, и не делаю так. Вроде работает.

о_О>с std::bind работать не будет

А можно чуть подробнее, почему?
PS std::bind использую редко
Маньяк Робокряк колесит по городу
Re[4]: Компараторы
От: о_О
Дата: 25.11.11 09:06
Оценка:
Здравствуйте, Marty, Вы писали:

M>Здравствуйте, о_О, Вы писали:


M>>>но я не помню, зачем, и не делаю так. Вроде работает.

о_О>>с std::bind работать не будет

M>А можно чуть подробнее, почему?


определяет типы, с которыми бинд работает
template<class Arg1, class Arg2, class Result>
  struct binary_function {
    typedef Arg1 first_argument_type;
    typedef Arg2 second_argument_type;
    typedef Result result_type;
  };


M>PS std::bind использую редко


ты многое теряешь такие вещи можно творить
Автор(ы): Bjorn Karlsson
Дата: 24.02.2006
Рассматриваются все типовые случаи применения bind — связывание свободных функций, функций-членов класов, переменных-членов, виртуальных функций, а также функциональная композиция. На простом примере поясняется идея, лежащая в основе реализации bind.
...
Re[2]: Компараторы
От: anomander  
Дата: 25.11.11 09:17
Оценка:
Здравствуйте, MasterZiv, Вы писали:

MZ>On 11/25/2011 01:43 AM, dlyas wrote:


>> компаратор. Теперь пусть я написал этот компаратор в каком-то виде. Но теперь

>> пишу функцию вида std::sort, пусть даже свой sort.
>> Как объявить эту функцию, как показать, что она принимает компаратор?

MZ>Если пишешь на шаблонах, то НИКАК.

MZ>Надо её просто объявить как какой-то параметр шаблона -- тип, и вызвать, и всё.

MZ>Быть может

>> где-то можно прочитать конкретный пример? Но будет куда лучше, если кто-нибудь
>> приведет его здесь. Потому что все, что я нахожу про компараторы — это как их
>> использовать.

MZ>Код стандартного std::sort смотри, и всё.


>> std::sort (begin, end, std::less<my_struct>);

>> ? и что это будет значить? Как мне этот less переопределить.

MZ>Тебе надо определить operator == и operator < для этого типа my_struct.


Как-то так


template<typename T, typename Comp>
bool compare(T const& a, T const& b, Comp comp)
{
    return comp(a, b);
}

int main(int argc, char *argv[])
{
    std::cout << compare(1, 2, std::less<int>());
    return 0;
}
Re[3]: Компараторы
От: Masterkent  
Дата: 25.11.11 10:54
Оценка:
о_О:

о_О>Здравствуйте, Marty, Вы писали:


M>>Вообще, my_struct_less вроде надо наследовать от std::binary_predicate

о_О>не знаю таких. знаю std::binary_function

M>>но я не помню, зачем, и не делаю так. Вроде работает.

о_О>с std::bind работать не будет

Чего это?
Re[4]: Компараторы
От: о_О
Дата: 25.11.11 11:27
Оценка:
Здравствуйте, Masterkent, Вы писали:

M>о_О:


о_О>>Здравствуйте, Marty, Вы писали:


M>>>Вообще, my_struct_less вроде надо наследовать от std::binary_predicate

о_О>>не знаю таких. знаю std::binary_function

M>>>но я не помню, зачем, и не делаю так. Вроде работает.

о_О>>с std::bind работать не будет

M>Чего это?


bind обязывает иметь в предикате определение result_type (закомменченое не работает):

template <typename T>
struct my_comp1
{
  bool operator()(const T& arg1, const T& arg2) const
  {
    return (arg1 < arg2);
   }
};

template <typename R, typename T>
struct my_comp2
{
  typedef R result_type;

  result_type operator()(const T& arg1, const T& arg2) const
  {
    return (arg1 < arg2);
   }
};

void wmain()
{
  std::vector<int> v;
  v.push_back(2), v.push_back(1), v.push_back(3);

  //auto comporator1 = std::bind(my_comp1<int>(), std::placeholders::_1, std::placeholders::_2);
  auto comporator2 = std::bind(my_comp2<int, bool>(), std::placeholders::_1, std::placeholders::_2);
  //std::sort(std::begin(v), std::end(v), comporator1);
  std::sort(std::begin(v), std::end(v), comporator2);
}
Re[5]: Компараторы
От: Masterkent  
Дата: 25.11.11 12:04
Оценка:
о_О:

о_О>bind обязывает иметь в предикате определение result_type


Конкретно про std::bind где такое сказано?

о_О>(закомменченое не работает):


У VC++10 очень убогая стандартная библиотека, которая даже скудные возможности компилятора не в полной мере использует. result_type был нужен до появления decltype (благодаря которому можно автоматически вывести тип результата), сейчас это просто костыль из прошлого.

Следующий код (я малость подкорректировал твой)

  Скрытый текст
#include <algorithm>
#include <functional>
#include <iterator>
#include <vector>

template <typename T>
struct my_comp1
{
  bool operator()(const T& arg1, const T& arg2) const
  {
    return (arg1 < arg2);
   }
};

template <typename R, typename T>
struct my_comp2
{
  typedef R result_type;

  result_type operator()(const T& arg1, const T& arg2) const
  {
    return (arg1 < arg2);
   }
};

int main()
{
  std::vector<int> v;
  v.push_back(2), v.push_back(1), v.push_back(3);

  auto comporator1 = std::bind(my_comp1<int>(), std::placeholders::_1, std::placeholders::_2);
  auto comporator2 = std::bind(my_comp2<int, bool>(), std::placeholders::_1, std::placeholders::_2);
  std::sort(std::begin(v), std::end(v), comporator1);
  std::sort(std::begin(v), std::end(v), comporator2);
}

без проблем компилится при использовании GNU C++ 4.7.0.
Re[6]: Компараторы
От: о_О
Дата: 25.11.11 12:33
Оценка:
Здравствуйте, Masterkent, Вы писали:

о_О>bind обязывает иметь в предикате определение result_type


M>Конкретно про std::bind где такое сказано?


некорректно выразился. для boost::bind и старых кривых std::bind (например из VS) это необходимо

M>У VC++10 очень убогая стандартная библиотека, которая даже скудные возможности компилятора не в полной мере использует. result_type был нужен до появления decltype (благодаря которому можно автоматически вывести тип результата), сейчас это просто костыль из прошлого.


M>Следующий код (я малость подкорректировал твой) без проблем компилится при использовании GNU C++ 4.7.0.


у gcc уже давно нормальная stl
Re[5]: Компараторы
От: aa_unique  
Дата: 25.11.11 17:59
Оценка:
MZ>>Нужно просто в my_struct определить operator < и operator ==
M>Про == забыл (или не знал). А он точно нужен? Там вроде в sort'е используются сравнения cmp(s1,s2) и cmp(s2,s1)

В std sort, map, multimap, set требуют только operator<. == не надо.
Re[6]: Компараторы
От: Marty Пират https://www.youtube.com/channel/UChp5PpQ6T4-93HbNF-8vSYg
Дата: 25.11.11 18:37
Оценка:
Здравствуйте, aa_unique, Вы писали:

MZ>>>Нужно просто в my_struct определить operator < и operator ==

M>>Про == забыл (или не знал). А он точно нужен? Там вроде в sort'е используются сравнения cmp(s1,s2) и cmp(s2,s1)

_>В std sort, map, multimap, set требуют только operator<. == не надо.


Ну и я о том же. Только не operator<, а функтор строгого сравнения, который в случае std::less реализуется через оператор operator<.
Маньяк Робокряк колесит по городу
Re: Компараторы
От: ononim  
Дата: 28.11.11 14:30
Оценка:
D>Вот есть std::sort, у него есть параметр — предикат сравнения. То есть компаратор. Теперь пусть я написал этот компаратор в каком-то виде. Но теперь пишу функцию вида std::sort, пусть даже свой sort.
Все мы когда-то писали свой sort.. Вот мой:
template<class T, class Pred = std::less<T>> class quicksort {
        static inline T* partition(T* from, T* back)
        {
                T* front  =  from;
                ++front;
                --back;
                while (front < back)
                {
                        while ((front < back) && Pred()(*front, *from)) ++front;
                        while ((front < back) && !Pred()(*back, *from)) --back;
                        std::swap(*front, *back);
                }

                if (Pred()(*from, *front)) --front;
                std::swap(*from, *front);
                return front;
        }

        static void __fastcall recurse(T* from, T* to)
        {
                if (from < to - 1)
                {
                        T* mid = partition(from, to);
                        recurse(from, mid);
                        recurse(mid + 1, to);
                }
        }


public:

        explicit quicksort(std::vector<T> &v)
        {
                const size_t l = v.size();
                if (l)
                {
                        T *p = &v.front();
                        recurse(p, p + l);
                }
        }
};


template<class V, class Pred> inline void QuickSortVector(V &v) {
        quicksort<V::value_type, Pred>((V &)v); }

template<class V> inline void QuickSortVector(V &v) {
        quicksort<V::value_type>((V &)v);
}


PS std::sort обычно быстрее
Как много веселых ребят, и все делают велосипед...
Re[2]: Компараторы
От: Roman Odaisky Украина  
Дата: 28.11.11 19:49
Оценка:
Здравствуйте, ononim, Вы писали:


O>template<class T, class Pred = std::less<T>> class quicksort {

O> static inline T* partition(T* from, T* back)
O> . . . Pred()(*front, *from)) . . .

Не так:

template <class Iterator>
void sort(Iterator first, Iterator last)
. . . *x < *y . . .

template <class Iterator, class Predicate>
void sort(Iterator first, Iterator last, Predicate p)
. . . p(*x, *y) . . .

Так можно передать объект в качестве предиката, а не создавать его конструктором. Это позволит выполнять сравнение с учетом каких-либо пользовательских данных. Например, сравнивать строки с учетом языковых особенностей, если язык задается во время выполнения: sort(first, last, UnicodeCollateComparator(CASE_INSENSITIVE, "de_AT")).
До последнего не верил в пирамиду Лебедева.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.