Определите std :: map с шаблоном типа Key на основе функции, полученной в качестве параметра - PullRequest
0 голосов
/ 21 октября 2018

Моя цель - иметь функцию, которая возвращает карту, которая может иметь тип Key, который изменяется в зависимости от функции, переданной в качестве параметра моей функции.

У меня есть следующая шаблонная функция (C ++11) пока что единственное компилируемое решение:

    template <typename Container, typename Function, typename KeyType>
    std::map< KeyType, std::vector<typename Container::value_type> > 
    group_by(Container &container, Function function, KeyType keyHint) { ...

Сейчас это позволяет мне использовать эту функцию следующим образом:

// the last parameter is just a type hint for the compiler
std::map<int, std::vector<int>> m = group_by(vec, func_that_returns_an_int, 1337);
...
std::map<int, std::vector<int>> m = group_by(vec, func_that_returns_an_int, -1);

// if we pass a function that returns bool, the map's key will be boolean
// the last parameter passed is just a hint for the compiler
std::map<bool, std::vector<int>> m = group_by(vec, is_even, true);
...
std::map<bool, std::vector<int>> m = group_by(vec, is_even, false);

Моя цель - не проходить мимослучайное значение для указания компилятору того, каким должен быть тип ключа карты, хотелось бы сделать что-то вроде этого:

std::map<int, std::vector<int>> m = group_by<int>(vec, func_that_returns_an_int);
...
std::map<bool, std::vector<int>> m = group_by<bool>(vec, is_even);

или это вообще возможно?

std::map<bool, std::vector<int>> m = group_by(vec, is_even);

Я поигрался с auto и decltype, чтобы посмотреть, не удастся ли намеку на компилятор с левой стороны операции.

auto group_by(Container &container, Function function) -> std::map< decltype(function(Container::value_type)), >

Ответы [ 2 ]

0 голосов
/ 21 октября 2018

Вы можете использовать std::result_of<>:

#include <map>
#include <vector>
#include <type_traits>

template <typename Container, typename Function, typename KeyType = std::result_of_t<Function()>>
auto group_by(Container c, Function f) -> std::map< KeyType, std::vector<typename Container::value_type>>
{
    return // ...
}

int bar() { return 42; }

int main()
{
    auto v = group_by(std::vector<double>{}, bar);
}
0 голосов
/ 21 октября 2018

Изменение параметра порядка или шаблона позволит вам вызвать его

group_by<int>(vec, func_that_returns_an_int);

Поэтому измените

template <typename Container, typename Function, typename KeyType>
std::map< KeyType, std::vector<typename Container::value_type> > 
group_by(Container &container, Function function, KeyType keyHint)

на

template <typename KeyType, typename Container, typename Function>
std::map< KeyType, std::vector<typename Container::value_type> > 
group_by(Container &container, Function function)

Для полного удаления KeyType, вы должны вывести его из других параметров:

template <typename Container, typename Function>
auto group_by(Container &container, Function function)
-> std::map<decltype(function(*container.begin())),
            std::vector<typename Container::value_type> > 
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...