Сначала я использую С++ 11 (и моя тема отстой).
То, что я пытаюсь сделать, это написать общую функцию шаблона, которая реализует что-то обычно называемое sort_by
на других языках программирования. Это предполагает вычисление произвольного критерия для каждого члена диапазона ровно один раз, а затем сортировку этого диапазона в соответствии с этими критериями. Такой критерий не должен быть POD, все, что он должен быть, менее чем сопоставимо. Для вещей, для которых std::less
не работает, вызывающий должен быть в состоянии предоставить свой собственный функтор сравнения.
Я успешно написал указанную функцию, которая использует следующую подпись:
template< typename Tcriterion
, typename Titer
, typename Tcompare = std::less<Tcriterion>
>
void
sort_by(Titer first, Titer last,
std::function<Tcriterion(typename std::iterator_traits<Titer>::value_type const &)> criterion_maker,
Tcompare comparator = Tcompare()) {
}
Его можно использовать, например. например:
struct S { int a; std::string b; double c; };
std::vector<S> s_vec{
{ 42, "hello", 0.5 },
{ 42, "moo!", 1.2 },
{ 23, "fubar", 0.2 },
};
sort_by1< std::pair<int, double> >(
s_vec.begin(), s_vec.end(),
[](S const &one_s) { return std::make_pair(one_s.a, one_s.c); }
);
Что мне не нравится в этом подходе, так это то, что я должен сам предоставить аргумент Tcriterion
, потому что компилятор не может вывести этот тип из выражения лямбда. Поэтому это не работает:
sort_by1(s_vec.begin(), s_vec.end(), [](S const &one_s) { return std::make_pair(one_s.a, one_s.c); });
clang 3.1 и gcc 4.7.1 оба коры на этом (gcc 4.7.1 даже лает на код выше, поэтому я думаю, я действительно делаю что-то неправильно здесь).
Однако, если я сначала назначу лямбда на std::function
, тогда по крайней мере clang 3.1 может вывести аргумент, то есть это работает:
typedef std::pair<int, double> criterion_type;
std::function<criterion_type(S const &)> criterion_maker = [](S const &one_s) {
return std::make_pair(one_s.a, one_s.c);
};
sort_by1(s_vec.begin(), s_vec.end(), criterion_maker);
Итак, мои вопросы: как мне изменить свою сигнатуру функции, чтобы мне не нужно было указывать один аргумент? И (возможно, связанный), как бы исправить мой пример, чтобы он работал с gcc?