Здравствуйте!
Я не очень знаю С++ и прошу помочь как новичку.
Вот есть std::sort, у него есть параметр — предикат сравнения. То есть компаратор. Теперь пусть я написал этот компаратор в каком-то виде. Но теперь пишу функцию вида std::sort, пусть даже свой sort.
Как объявить эту функцию, как показать, что она принимает компаратор? Быть может где-то можно прочитать конкретный пример? Но будет куда лучше, если кто-нибудь приведет его здесь. Потому что все, что я нахожу про компараторы — это как их использовать.
И еще вопрос. Пусть у меня есть структура my_struct.
Я могу написать:
std::sort (begin, end, std::less<my_struct>);
? и что это будет значить? Как мне этот less переопределить.
Здравствуйте, dlyas, Вы писали:
D>Здравствуйте! D>Я не очень знаю С++ и прошу помочь как новичку.
D>Вот есть std::sort, у него есть параметр — предикат сравнения. То есть компаратор. Теперь пусть я написал этот компаратор в каком-то виде. Но теперь пишу функцию вида std::sort, пусть даже свой sort. D>Как объявить эту функцию, как показать, что она принимает компаратор? Быть может где-то можно прочитать конкретный пример? Но будет куда лучше, если кто-нибудь приведет его здесь. Потому что все, что я нахожу про компараторы — это как их использовать.
D>И еще вопрос. Пусть у меня есть структура my_struct. D>Я могу написать:
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, но я не помню, зачем, и не делаю так. Вроде работает.
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.
Это делать не надо, есть уже стандартный less. Но можно.
И ты всё перепутал. Если делать operator() для изображения из него LESS
для этого твоего типа, то это должен быть отдельный класс, не в my_struct.
Можно конечно в my_struct сделать статическую функцию, но опять-таки
это не то, что ты написал.
Нужно просто в my_struct определить operator < и operator ==
Здравствуйте, Marty, Вы писали:
M>Вообще, my_struct_less вроде надо наследовать от std::binary_predicate
не знаю таких. знаю std::binary_function
M>но я не помню, зачем, и не делаю так. Вроде работает.
с std::bind работать не будет
Здравствуйте, 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)
Здравствуйте, 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;
};
Здравствуйте, 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.
о_О:
о_О>Здравствуйте, Marty, Вы писали:
M>>Вообще, my_struct_less вроде надо наследовать от std::binary_predicate о_О>не знаю таких. знаю std::binary_function
M>>но я не помню, зачем, и не делаю так. Вроде работает. о_О>с std::bind работать не будет
Здравствуйте, Masterkent, Вы писали:
M>о_О:
о_О>>Здравствуйте, Marty, Вы писали:
M>>>Вообще, my_struct_less вроде надо наследовать от std::binary_predicate о_О>>не знаю таких. знаю std::binary_function
M>>>но я не помню, зачем, и не делаю так. Вроде работает. о_О>>с std::bind работать не будет
M>Чего это?
bind обязывает иметь в предикате определение result_type (закомменченое не работает):
о_О: о_О>bind обязывает иметь в предикате определение result_type
Конкретно про std::bind где такое сказано? о_О>(закомменченое не работает):
У VC++10 очень убогая стандартная библиотека, которая даже скудные возможности компилятора не в полной мере использует. result_type был нужен до появления decltype (благодаря которому можно автоматически вывести тип результата), сейчас это просто костыль из прошлого.
Здравствуйте, Masterkent, Вы писали:
о_О>bind обязывает иметь в предикате определение result_type
M>Конкретно про std::bind где такое сказано?
некорректно выразился. для boost::bind и старых кривых std::bind (например из VS) это необходимо
M>У VC++10 очень убогая стандартная библиотека, которая даже скудные возможности компилятора не в полной мере использует. result_type был нужен до появления decltype (благодаря которому можно автоматически вывести тип результата), сейчас это просто костыль из прошлого.
M>Следующий код (я малость подкорректировал твой) без проблем компилится при использовании GNU C++ 4.7.0.
MZ>>Нужно просто в my_struct определить operator < и operator == M>Про == забыл (или не знал). А он точно нужен? Там вроде в sort'е используются сравнения cmp(s1,s2) и cmp(s2,s1)
В std sort, map, multimap, set требуют только operator<. == не надо.
Здравствуйте, 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<.
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 обычно быстрее
Как много веселых ребят, и все делают велосипед...
Так можно передать объект в качестве предиката, а не создавать его конструктором. Это позволит выполнять сравнение с учетом каких-либо пользовательских данных. Например, сравнивать строки с учетом языковых особенностей, если язык задается во время выполнения: sort(first, last, UnicodeCollateComparator(CASE_INSENSITIVE, "de_AT")).