Как правильно направить Invocable типы

Вопрос задан: 3 года назад Последняя активность: 3 года назад
up 6 down

Я действительно хотел бы использовать cmcstl2, Реализация диапазонов TS. Мне особенно нравится необязательные выступы на каждую STL-алгоритме. Invocable типы получить перенаправлены (EHM... или нет), как это: (min_element.hpp)

template <ForwardIterator I, Sentinel<I> S,
    class Comp = less<>, class Proj = identity>
requires
    IndirectStrictWeakOrder<
        Comp, projected<I, Proj>>()
I min_element(I first, S last, Comp comp = Comp{}, Proj proj = Proj{});

template <ForwardRange Rng, class Comp = less<>, class Proj = identity>
requires
    IndirectStrictWeakOrder<
        Comp, projected<iterator_t<Rng>, Proj>>()
safe_iterator_t<Rng>
min_element(Rng&& rng, Comp comp = Comp{}, Proj proj = Proj{})
{
    return __stl2::min_element(__stl2::begin(rng), __stl2::end(rng),
        __stl2::ref(comp), __stl2::ref(proj));
}

Как Справочно: диапазон-v3 библиотека реализует это следующим образом: (min_element.hpp)

struct min_element_fn {
        template<typename I, typename S, typename C = ordered_less, typename P = ident,
            CONCEPT_REQUIRES_(ForwardIterator<I>() && Sentinel<S, I>() &&
                IndirectRelation<C, projected<I, P>>())>
        I operator()(I begin, S end, C pred = C{}, P proj = P{}) const;

        template<typename Rng, typename C = ordered_less, typename P = ident,
            typename I = range_iterator_t<Rng>,
            CONCEPT_REQUIRES_(ForwardRange<Rng>() &&
                IndirectRelation<C, projected<I, P>>())>
        range_safe_iterator_t<Rng> operator()(Rng &&rng, C pred = C{}, P proj = P{}) const
        {
            return (*this)(begin(rng), end(rng), std::move(pred), std::move(proj));
        }
};

Теперь я пытаюсь понять разницу и рассуждения обоих подходов. Почему я должен взять Invocable типы по значению в любом случае? Почему я не должны использовать идеальную переадресацию для этих типов?

Я понимаю, что второй подход более, чем я для первого, так как я понимаю методологию принятия аргументов поглотителей по значению.

2 ответа

Возможно, для Вашего проекта будут необходимы бесплатные векторные карты. На нашем сайте представлены карты для всех стран.

Реклама

up 8 down accepted

По двум причинам:

  1. Мое чтение стандартной спецификации библиотеки является то, что алгоритмы могут копировать объекты функции пользователя столько раз, сколько они хотели, но указаны для выполнения всех вызовов на одном экземпляре. Поскольку cmcstl2 часто орудия алгоритмов в терминах других алгоритмов, самый простой способ выполнить это требование, чтобы внутренне передать функции объектов по reference_wrapper. Например, binary_search звонки lower_bound и затем определяет, является ли элемент обозначается нижняя граница точное совпадение. Она проходит reference_wrappers для сравнения и функции проекта объектов к lower_bound так что он может вызывать одни и те же экземпляры позже.

  2. Большие и/или изменяемые объекты функции могут быть редкими, но нет никаких причин, они должны быть плохо поддерживаются в стандартной библиотеке. Копирование обычно дешевы, и перемещение почти всегда так, но передача по ссылке не «никогда» дорого. cmcstl2 минимизирует копирует хода функциональных объектов пользователя. (Воздушные котировки на «никогда» не там, чтобы указать, что передача по ссылке ставит существенно большую нагрузку на оптимизатор, увеличивая время компиляции и потенциально генерировать плохой код в угловых случаях, если анализ псевдоним смущают ссылки на объекты функции.)

Есть некоторые очевидные дыры в этом рассуждении. В первую очередь для меня «Если функция объекты могут быть с пользой отслеживанием состояния, не должны быть алгоритмы их возвращения, чтобы сохранить это состояние, как это делает std::for_each?»Конструкция cmcstl2 существенно нарушает какие элементы программирования вызовов„Закон Полезного Возвращения“мы должны осложнить подписи стандартных алгоритмов для возврата целых три функциональных объектов. - говорят, компаратор и два выступа - для размещения 0,1 ?% использование случае я думаю, что очевидный ответ здесь «нет», особенно с учетом того, что обходной путь так просто: передайте reference_wrapper.

Итак, почему cmcstl2 вообще - и Standard C++ 's std::for_each в частности - выйти из своего способа размещения больших и/или изменяемых функциональных объектов, когда обходной путь так же, чтобы передать reference_wrapper? Похоже, дизайнер cmcstl2 сделал ту же ошибку, здесь как и ПРГ, когда они сделали std::for_each вернуть его объект функции.

up 7 down

Это традиционное принять Invocable по стоимости, поскольку они, как правило, имеют небольшой sizeof, Например, в указатель на функцию или лямбда с несколькими захватами. Такие параметры функции, в соответствии с ABI, передаются в регистрах машины, или полностью устранены в случае less или же identity. С другой стороны, передача по ссылке стремится вытолкнуть компилятор поставить реальный объект в памяти.

Более крупные объекты, или те, со значительным изменяемым состоянием, могут быть пропущены через std::ref. Результирующий std::reference_wrapper тривиальный-копируемый и большой, как указатель, так что это эффективно передаются по значению.

Ошибка 505

Что-то пошло не так

Попробуйте воспользоваться поиском