Nano Hash - криптовалюты, майнинг, программирование

Почему в стандарте С++ 17 не было выведено частичных аргументов шаблона класса?

Я надеялся, что в одном из мест, где я смогу использовать новый вывод аргумента шаблона, было построение std::set/std::map/любых других контейнеров с пользовательскими компараторами. Моя цель — создать однострочный оператор, который создаст эффективный набор. с лямбда компаратором. Что я могу сделать с С++ 11:

std::set<int, std::function<bool(int, int)>> s([](int a, int b) {return a > b;});

Но так как он использует std::function, он заметно медленнее.

Другой вариант:

auto mycomp = [](int a, int b) {return a > b; };
std::set<int, decltype(mycomp)> s(mycomp);

Он выполняет свою работу, но 1) требует 2 строки и создание переменной mycomp 2) мне нужно явно передать тип mycomp.

Как я читал на справочных страницах, ни в одном из стандартных контейнеров нет руководства по дедукциям для такой ситуации. К сожалению, я боюсь, что это невозможно сделать даже с текущим стандартом языка (С++ 17), как можно найти:

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

Что стоит за этим? Почему они не разрешили частичный вывод аргумента? Я предполагаю, что есть некоторые проблемы с этим, которые я упускаю из виду, но, на мой взгляд, это было бы более чем полезно.


  • Частичный вычет был в предложении сначала, но был удален. См. c17-class-template-partial-deduction. 28.05.2018
  • @Kaznov: моя цель - создать однострочный оператор, который создаст эффективный набор с компаратором лямбда. ... почему это ваша цель? Что плохого в том, чтобы просто создать структуру с перегрузкой operator()? Почему вы должны (или даже хотите) использовать лямбда-выражения? 28.05.2018

Ответы:


1

В одну строку (С++ 17)

std::set s(std::initializer_list<int>{}, [](int a, int b) {return a > b; });
28.05.2018
  • Спасибо! Я не знал о существовании этого конструктора. Что ж, это решает проблему с контейнерами. 28.05.2018
  • @Kaznov - работает, но не очень элегантно: этот std::initializer_list<int>{}, просто чтобы указать тип int, очень уродлив. 28.05.2018

  • 2

    В качестве альтернативы вы все еще можете сделать старый make_xxx

    template <typename T, typename COMP>
    std::set<T, COMP> make_set(COMP comp)
    {
        return std::set<T, COMP>{comp};
    }
    
    
    auto s = make_set<int>([](int a, int b) {return a > b; });
    
    28.05.2018

    3

    То, что вы должны сделать, это написать тип функтора компаратора, поэтому вам не нужно проксировать его при использовании вашего набора. Это будет намного больше строк кода (зверство!), но лучше практически во всех отношениях:

    struct MyComparator
    {
        bool operator()(int a, int b) const { ...; }
    };
    using MySet = std::set<int, MyComparator>;
    

    И с тех пор вы просто создаете свой собственный отсортированный набор там, где вам это нужно.

    28.05.2018
  • Я знаю, что это лучший способ решения этой проблемы, но я искал самый компактный. 28.05.2018
  • @Kaznov: Почему он должен быть компактным? Наличие большой лямбды в середине специализации шаблона не делает ваш код более удобным для чтения. Этот менее компактный код гораздо легче читается, чем лямбда. 28.05.2018
  • Я искал самый быстрый способ сделать это, чтобы использовать его в алгоритмическом соревновании. Там вам все равно, как выглядит код, чем короче, тем лучше. 28.05.2018

  • 4

    Из-за неоднозначности это происходит, когда присутствует параметр шаблона со значением по умолчанию. Также, в случае вариативных шаблонов.

    28.05.2018
    Новые материалы

    Кластеризация: более глубокий взгляд
    Кластеризация — это метод обучения без учителя, в котором мы пытаемся найти группы в наборе данных на основе некоторых известных или неизвестных свойств, которые могут существовать. Независимо от..

    Как написать эффективное резюме
    Предложения по дизайну и макету, чтобы представить себя профессионально Вам не позвонили на собеседование после того, как вы несколько раз подали заявку на работу своей мечты? У вас может..

    Частный метод Python: улучшение инкапсуляции и безопасности
    Введение Python — универсальный и мощный язык программирования, известный своей простотой и удобством использования. Одной из ключевых особенностей, отличающих Python от других языков, является..

    Как я автоматизирую тестирование с помощью Jest
    Шутка для победы, когда дело касается автоматизации тестирования Одной очень важной частью разработки программного обеспечения является автоматизация тестирования, поскольку она создает..

    Работа с векторными символическими архитектурами, часть 4 (искусственный интеллект)
    Hyperseed: неконтролируемое обучение с векторными символическими архитектурами (arXiv) Автор: Евгений Осипов , Сачин Кахавала , Диланта Хапутантри , Тимал Кемпития , Дасвин Де Сильва ,..

    Понимание расстояния Вассерштейна: мощная метрика в машинном обучении
    В обширной области машинного обучения часто возникает необходимость сравнивать и измерять различия между распределениями вероятностей. Традиционные метрики расстояния, такие как евклидово..

    Обеспечение масштабируемости LLM: облачный анализ с помощью AWS Fargate и Copilot
    В динамичной области искусственного интеллекта все большее распространение получают модели больших языков (LLM). Они жизненно важны для различных приложений, таких как интеллектуальные..