Как преобразовать std :: map в std :: function?

std::map<K,V> реализует функцию частичный типа std::function<V(K)>.

Я пытаюсь реализовать универсальную функцию map2fun(), которая превращает std::map в объект std::function.

Следующее не компилируется:

template<typename M>
function<M::mapped_type(M::key_type)> map2fun(M& m)
{
  return [&m](M::key_type k)
    {
      return m[k];
    };
}

Мои вопросы:

  • Доступна ли аналогичная функциональность в STL для C++ 11?
  • Если нет, как я могу реализовать это с помощью C++ 11?

Это намеренно возвращаемое значение, а не ссылка? Разрешено ли изменять карту намеренно?

Jarod42 28.05.2018 13:51

@ Jarod42 Что касается моего текущего уровня обучения: нет, это не намеренно.

ziggystar 28.05.2018 14:06

@ziggystar - ответ улучшен (после комментария Jarod42).

max66 28.05.2018 14:16
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
3
3
91
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Is there a similar functionality available in the STL for C++11?

Нет, насколько я знаю.

Но сам std::map - это «аналогичный функционал, доступный в STL для C++ 11» (а также C++ 98), ИМХО.

If not, how can I implement it with C++11?

Добавление typename в ваш код, например

template <typename M>
std::function<typename M::mapped_type(typename M::key_type)> map2fun (M & m)
 { return [&m](typename M::key_type k) { return m[k]; }; }

Но я нахожу более ясным этот путь

template <typename K, typename V>
std::function<V(K)> m2f2 (std::map<K, V> & m)
 { return [&m](K k) { return m[k]; }; }

но, как указал Jarod42 (спасибо!), этот перехватывает только std::map (не std::unordered_map, не похожие (также настраиваемые) типы), поэтому вы можете сделать его более гибким, как показано ниже.

template <template <typename ...> class C, typename K, typename V,
          typename ... Ts>
std::function<V(K)> m2f2 (C<K, V, Ts...> & m)
 { return [&m](K k) { return m[k]; }; }

и, начиная с C++ 17, можно упростить следующим образом

template <template <typename ...> class C, typename K, typename V>
std::function<V(K)> m2f2 (C<K, V> & m)
 { return [&m](K k) { return m[k]; }; }

В качестве указателя от Jarod42 (еще раз спасибо!) Эта версия шаблона-шаблона включена также для других контейнеров (std::vector, например), и это дает очень уродливое сообщение об ошибке (не простой и не реализованный "map2fun ()").

Вы можете избежать этой проблемы, используя SFINAE, включив функцию только (в качестве примера), если контейнер C определяет тип mapped_type; я имею в виду

template <template <typename ...> class C, typename K, typename V,
          typename ... Ts, typename = typename C<K, V, Ts...>::mapped_type>
std::function<V(K)> m2f2 (C<K, V, Ts...> & m)
 { return [&m](K k) { return m[k]; }; }

Но теперь моя более простая версия сложнее твоей оригинальной :(.

Ниже приведен полный рабочий двойной пример.

#include <map>
#include <iostream>
#include <functional>
#include <unordered_map>

template <typename M>
std::function<typename M::mapped_type(typename M::key_type)> m2f1 (M & m)
 { return [&m](typename M::key_type k) { return m[k]; }; }

template <template <typename ...> class C, typename K, typename V,
          typename ... Ts, typename = typename C<K, V, Ts...>::mapped_type>
std::function<V(K)> m2f2 (C<K, V, Ts...> & m)
 { return [&m](K k) { return m[k]; }; }

int main ()
 {
   std::map<int, long> m1 {{0, 1L}, {1, 2L}, {2, 4L}, {3, 8L}};
   std::unordered_map<int, long> m2 {{0, 1L}, {1, 2L}, {2, 4L}, {3, 8L}};

   auto l1 { m2f1(m1) };
   auto l2 { m2f2(m2) };
   auto l3 { m2f1(m1) };
   auto l4 { m2f2(m2) };

   std::cout << l1(2) << std::endl;
   std::cout << l2(2) << std::endl;
   std::cout << l3(2) << std::endl;
   std::cout << l4(2) << std::endl;
 }

опередить меня :(

UmNyobe 28.05.2018 13:28

@UmNyobe - извините :-)

max66 28.05.2018 13:31

Первый способ также позволит std::unordered_map без дополнительной перегрузки, кстати.

Jarod42 28.05.2018 14:08

@ Jarod42 - Вы правы; но шаблоны-шаблоны и вариативные шаблоны могут помочь. Ответ изменен. Спасибо!

max66 28.05.2018 14:17

Теперь вы принимаете std::vector, даже если у вас будет ошибка внутри функции.

Jarod42 28.05.2018 14:35

@ Jarod42 - да ... очень уродливая ошибка ... добавлена ​​версия с поддержкой SFINAE для перехвата только типов с mapped_type внутри ... но теперь моя упрощенная версия сложнее оригинальной OP :(

max66 28.05.2018 14:51

Я бы остановился на конкретных версиях для std::map / std::unordered_map, которые являются наиболее читаемыми и в большинстве случаев их должно хватить.

Jarod42 28.05.2018 17:37

Другие вопросы по теме