Pull to refresh

Comments 14

Я, наверное, не совсем понял постановку задачи.
А не проще ли было вынести «длинную обработку it» в отдельную функцию?
Объединение циклов — в самой постановке задачи. Не могу целиком привести условие, хотя бы из-за того, что слишком долго. Семантически там нужно сделать одно и то же действие N=2 раза в разном порядке. К тому же если N не 2 а 1000, то просто функция уже не прокатит
Однако… А ведь можно уложиться только в одни стандартные возможности библиотеки.

    typedef std::multiset<int, std::function<bool(int,int)>> Set;
    Set set0([](int a, int b){ return a < b; });
    Set set1([](int a, int b){ return a > b; });
    Set sets[] = {set0, set1};

    for (size_t i = 0; i < 2; ++i) {
        for (auto const& val: sets[i]) {

        }       
    }
Или даже так, если хочется, чтобы было короче :)

    Set set0(bind(less<int>(), _1, _2));
    Set set1(bind(less<int>(), _2, _1));
bind(less(), _1, _2) — тавталогия?

Еще короче:
    Set set0(less<int>());
    Set set1(greater<int>());


А вообще очень хорошая идея с function, я не достаточно знаю с++11, чтобы самому догадаться, спасибо
>> bind(less(), _1, _2) — тавталогия?

Иначе не будет компилироваться (по крайней мере в 12 студии). Вообще, это всё фичи из boost и могут использоваться без с++11.
В gcc-4.7 такое компилируется и работает:
		typedef std::multiset<int, std::function<bool(int,int)>> Set4;
		Set4 sets4[N] = {Set4(std::less<int>()), Set4(std::bind(std::less<int>(), _2, _1))};

Не могу понять, почему в принципе в вс12 может не компилироваться такой код: bind(less(), _1, _2) подходит под тип function<bool(int,int)>> а less() — нет?
Может быть из-за того, что less::operator()(int const&, int const&) определен с параметрами int const&, а не int, и вариант:
        typedef std::multiset<int, std::function<bool(int const&, int const&)>> Set4;
        Set4 sets4[N] = {Set4(std::less<int>()), Set4(std::bind(std::less<int>(), _2, _1))};

будет работать и в вс12?
В пример программы внесны изменения, в частности, добавлены варианты использования std::function — спасибо Unrul
Нужно заметить, что мультисеты, параметризованные «по возрастанию» и «по убыванию» — это, фактически, мультисеты разных типов.
Пусть с точки зрения компилятора, они однотипны, так же, как однотипны объекты, доступные через однотипные указатели.
Это такой ad hoc полиморфизм.

Поэтому при работе с ними нужна определённая гигиена.
Скажем,
my_multiset_compiletime<ASCENDING> ac;
my_multiset_compiletime<DESCENDING> dc;
my_multiset_runtime ar(ASCENDING);
my_multiset_runtime dr(DESCENDING);

ac.insert(1); ac.insert(3); ac.insert(2); // {1,2,3}

// поскольку между разнотипными мультисетами нет оператора присваивания, - явно копируем данные
// ну или, если мы делаем свой класс мультисета, то пишем шаблонный оператор присваивания...

ar.insert(ac.begin(), ac.end()); // {1,2,3}
dc.insert(ac.begin(), ac.end()); // {3,2,1}

// а вот между отнотипными - оператор присваивания есть из коробки

dr = ar; // {1,2,3}, заодно скопировали настройки компаратора!!!

Вообще, начали с того, что хотели припахать foreach для перебора в двух разных направлениях, а вместо этого стали делать разные компараторы.
Не проще ли было взять адаптер диапазона?
#include <boost/range/adaptor/reversed.hpp>

.....

std::multiset<int> ms;
for(auto i : ms) { ..... }
for(auto i : boost::adaptors::reverse(ms)) { ..... }

важнее не перебрать сеты в разных направлениях, а объединить циклы
Зачем городить огород с компараторами, если достаточно лямбды и итераторов?

#include <iostream>
#include <set>
#include <algorithm>

using namespace std;

int main()
{
    multiset<int> set0 = { 0, 1, 2 };
    multiset<int> set1 = { 3, 4, 5 };

    auto& process = [&](int n) {
        cout << n << ' ';
    };
    for_each(set0.begin(), set0.end(), process);
    for_each(set1.rbegin(), set1.rend(), process);

    return 0;
}

опять же, самым главным является объединение циклов, а не свертки тела цикла в функцию
Sign up to leave a comment.

Articles