LINUX.ORG.RU

продемонстрируйте пожалуйста мощь шаблонов и STL


0

0

есть std::vector< std::pair <std::string, double> > vec;

нужно отсортировать его по числу (double). то есть написать:

std::sort( vec.begin(), vec.end(), XXX );

вот на место XXX нужно поставить компаратор. Написать отдельный тип для этого я и сам смогу, но хотелось бы обойтись без объявлений типов, а просто на место XXX забабахать какое-нибудь хитрое выражение ala bind1st. Можно такое сделать?

★★★★★

продемонстрируйте пожалуйста мощь шаблонов и STL

Можно, но пишется это выражение долго, мучительно и через жопу («написать отдельный тип» как правило гораздо проще). Проще всего это делается через библиотеки шаблонов, поддерживающие лямбда-подобные конструкции (по-моему boost::lambda, и ещё что-то из буста позволяло это делать). И в случае если где-нибудь допустишь ошибку (а это весьма вероятно, т. к. конструкция получается громоздкая и плохочитаемая), то придётся внимательно изучать вывод компилятора размером с несколько экранов.

В общем, весьма унылое это занятие - писать в функциональном стиле на c++. Не надо так делать. Не предназначен он для этого.

slav ★★ ()

продемонстрируйте пожалуйста мощь шаблонов и STL

если есть желание, то можно уже пользоваться лямбдами - в gcc 4.4 и msvc 2010 они поддерживаются

lester ★★★★ ()

продемонстрируйте пожалуйста мощь шаблонов и STL

и где там решение? они пишут отдельную функцию для этого. я не хочу тратить строки на мусор. Я хочу скомпоновать std::greater и т.п. в одно выражение, которое поставить на место XXX.

dilmah ★★★★★ ()

Re: продемонстрируйте пожалуйста мощь шаблонов и STL

Я хочу скомпоновать std::greater и т.п. в одно выражение, которое поставить на место XXX.

А почему не сделать локальный класс?

void SomeClass::someMethod() {
  struct Cmp : public std::binary_function <...> {
    int operator()(double arg1,double arg2) {
       ....
    }
  }
}

Absurd ★★★ ()

продемонстрируйте пожалуйста мощь шаблонов и STL

ну это уже получше. Меня именно это и волновало — оторванность сущности (компаратора) от того единственного места для которого эта сущность нужна.

dilmah ★★★★★ ()

продемонстрируйте пожалуйста мощь шаблонов и STL

Давайте не будем усложнять прекрасный и лаконичный C++. Вот мое решение задачи:

#include <string>
#include <iostream>
#include <vector>
#include <algorithm>

typedef std::pair<std::string, double> pair_type;

bool LessFuncForPairType(pair_type const& v1, pair_type const& v2)
{
return v1.second < v2.second;
}

void FillVector(std::vector<pair_type>& v)
{
pair_type p;
p.first = "second";
p.second = 5.25;
v.push_back(p);
p.first = "last";
p.second = 31.57;
v.push_back(p);
p.first = "first";
p.second = 0.15;
v.push_back(p);
p.first = "third";
p.second = 14.11;
v.push_back(p);
}

void ShowVector(std::vector<pair_type> const& v)
{
std::cout << "vector contents: " << std::endl;
std::vector<pair_type>::const_iterator ender = v.end();
std::vector<pair_type>::const_iterator i;
for (i = v.begin(); i != ender; i++)
std::cout << i->first << ", " << i->second << std::endl;
}

int main()
{
std::vector<pair_type> vec;

FillVector(vec);
ShowVector(vec);

std::sort(vec.begin(), vec.end(), LessFuncForPairType);

ShowVector(vec);

return 0;
}



---------------
Буду рад ответить на любые ваши вопросы
codebaker...gmail...com

anonymous ()

Re: продемонстрируйте пожалуйста мощь шаблонов и STL

Пока делал кросспост в песочницу Хабра, придумал, как улучшить компаратор:

template <typename T1, typename T2>
bool ComparePairBySecondElement(std::pair<T1,T2> const& v1, std::pair<T1,T2> const& v2)
{
return v1.second < v2.second;
}

---------------
Буду рад ответить на любые ваши вопросы
codebaker...gmail...com

anonymous ()

продемонстрируйте пожалуйста мощь шаблонов и STL

#include <vector>
#include <string>
#include <boost/bind.hpp>
#include <iostream>
#include <algorithm>


typedef std::pair<std::string, double> cont_type;
std::vector< cont_type > vec;



int main()
{
vec.push_back(std::make_pair("bugoga", 10));
vec.push_back(std::make_pair("loh", 20));
vec.push_back(std::make_pair("hren", 15));

std::sort(vec.begin(), vec.end(), boost::bind(std::less<double>(), boost::bind(&cont_type::second, _1), boost::bind(&cont_type::second, _2)));

std::cout << vec[0].first << ", " << vec[0].second << std::endl;
std::cout << vec[1].first << ", " << vec[1].second << std::endl;
std::cout << vec[2].first << ", " << vec[2].second << std::endl;
return 0;
}

P1XeL ()

продемонстрируйте пожалуйста мощь шаблонов и STL

std::sort(vec.begin(), vec.end(), boost::bind(std::less<double>(), boost::bind(&cont_type::second, _1), boost::bind(&cont_type::second, _2)));

По до мной только что образовался тепленький, дымящийся кирпич.

baverman ★★★ ()

продемонстрируйте пожалуйста мощь шаблонов и STL

Если ты не понимаешь шаблонов, то это твои проблемы, шаблоны давно уже вошли в практику программирования на плюсах. man александреску

P1XeL ()

продемонстрируйте пожалуйста мощь шаблонов и STL

Еще раз повторяю, если не умеешь пользоваться шаблонами. то это твои проблемы.

Почитай для чего и как создавался stl.

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


template <typename Type> void my_sort(std::vector<Type> &vec)
{
std::sort(vec.begin(), vec.end(), std::less<Type>());
}

std::vector<int> t;

int main()
{
t.push_back(10);
t.push_back(30);
t.push_back(20);
t.push_back(15);

my_sort(t);

std::cout << t[0] << std::endl;
std::cout << t[1] << std::endl;
std::cout << t[2] << std::endl;
std::cout << t[3] << std::endl;
}

P1XeL ()

продемонстрируйте пожалуйста мощь шаблонов и STL

> Если шаблоны так прекрасны, почему нельзя написать

std::sort(vec)

Потому что стандартный operator< для std::pair сравнивает по первому элементу пары.

bvvv ()

продемонстрируйте пожалуйста мощь шаблонов и STL

Какой чудесный лаконичный кусок крестятины! Лисп по сравнению с сиим кодом, которым, право, мог бы гордиться Александреску, выглядит унылыми булшитом:

(map nil (lambda (x) (format t "~a, ~a~%" (car x) (cdr x)))
     (sort '(("bugoga" . 10) ("lol" . 20) ("hren" . 15)) #'< :key #'cdr))

mv ★★★★★ ()

продемонстрируйте пожалуйста мощь шаблонов и STL

А почему просто не перегрузить оператор '<' в простейшем производном классе? Наверняка в библиотеке он объявлен как virtual.

Кроме того, есть еще более простое решение: обернуть в класс, с обратным порядком аргументов в паре, после чего использовать все стандартное.

annoynimous ★★★★★ ()

продемонстрируйте пожалуйста мощь шаблонов и STL

Более, того, класс надо сделать ссылочным (кажется, это называется «интерфейсный указатель») и тогда никакого излишних накладных расходов, кроме одного косвенного обращения

annoynimous ★★★★★ ()

продемонстрируйте пожалуйста мощь шаблонов и STL

в gcc 4.4 должно как-то так быть:

std::sort(
    vec.begin(),
    vec.end(),
    [bool](
        std::pair <std::string, double> x,
        std::pair <std::string, double> y )
    { return x.second < y.second; } );
lester ★★★★ ()

продемонстрируйте пожалуйста мощь шаблонов и STL

Если предусмотрительно сделать typedef и не указывать явно возвращаемый тип, то все смотрится просто и красиво:

std::sort( vec.begin(), vec.end(), []( myT x, myT y ) { return x.second < y.second; } );

lester ★★★★ ()

продемонстрируйте пожалуйста мощь шаблонов и STL

> Если предусмотрительно сделать typedef и не указывать явно возвращаемый тип, то все смотрится просто и красиво: std::sort( vec.begin(), vec.end(), []( myT x, myT y ) { return x.second < y.second; } );

Если натянуться задом на кактус и при этом улыбаться, то никто не узнает, как вам на самом деле больно.

mv ★★★★★ ()

продемонстрируйте пожалуйста мощь шаблонов и STL

> Если натянуться задом на кактус и при этом улыбаться, то никто не узнает, как вам на самом деле больно.

так вот что чувствуют лисперы..., сочувствую

lester ★★★★ ()

продемонстрируйте пожалуйста мощь шаблонов и STL

> так вот что чувствуют лисперы..., сочувствую

У лисперов боль в заднице бывает (идеального ЯП не существует), но к тому моменту крестофилы уже давно жопным взрывом разбросаны кусками по округе.

mv ★★★★★ ()

продемонстрируйте пожалуйста мощь шаблонов и STL

> долгое общение с лиспом отложило отпечаток на ваши ассоциации

У меня хоть фантазия есть, в отличие от участников комитета по стандартизации C++. Эти кексы даже PITA не в том месте делают.

mv ★★★★★ ()

продемонстрируйте пожалуйста мощь шаблонов и STL

Меня это устраивает, если кроме этого больше ничего городить не надо. По семантике оно не на много от лиспа отличается. Ну, разве что, тут бы ещё foreach пригодился, но он в boost'е есть. Ты же сам ведь не будешь спорить, что таки лямбды в частности и в функциональный подход, употреблённый в тему, код укорачивают и упрощают для понимания?

mv ★★★★★ ()

продемонстрируйте пожалуйста мощь шаблонов и STL

> Ну, разве что, тут бы ещё foreach пригодился

опять же с выводом типов он делается одним макросом

> Ты же сам ведь не будешь спорить, что таки лямбды в частности и в функциональный подход, употреблённый в тему, код укорачивают и упрощают для понимания?


нет

lester ★★★★ ()

продемонстрируйте пожалуйста мощь шаблонов и STL

> доо

Увидев 2 строки на лиспе вместо 20 на плюсах не задуматься может только человек без фантазии. Для обычного, усреднённого программирования, т.е. процентов 90% от всех задач, Лисп лучше.

mv ★★★★★ ()

продемонстрируйте пожалуйста мощь шаблонов и STL

> Еще раз повторяю, если не умеешь пользоваться шаблонами. то это твои проблемы.

А твоя проблема в том, что ты непонятно зачем пишешь какие-то мутные примеры. Готовишься к выступлению в чемпионате по Boost?

tailgunner ★★★★★ ()

продемонстрируйте пожалуйста мощь шаблонов и STL

> Увидев 2 строки на лиспе вместо 20 на плюсах не задуматься может только человек без фантазии

хочешь я тебе на С++ все напишу короче чем предложили выше и тоже влеплю все в две строки?

lester ★★★★ ()

продемонстрируйте пожалуйста мощь шаблонов и STL

> хочешь я тебе на С++ все напишу короче чем предложили выше и тоже влеплю все в две строки?

Давай в одну, чего уж там...

mv ★★★★★ ()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.