模板函数分组值的更优雅方式是什么?

时间:2017-01-08 00:29:16

标签: c++ lambda decltype

以下代码对具有通用分组lambda的任何容器的值进行分组:

template<class Iterator, class GroupingFunc,
         class T = remove_reference_t<decltype(*declval<Iterator>())>,
         class GroupingType = decltype(declval<GroupingFunc>()(declval<T&>()))>
auto groupValues(Iterator begin, Iterator end, GroupingFunc groupingFunc) {
    map<GroupingType, list<T>> groups;
    for_each(begin, end,
        [&groups, groupingFunc](const auto& val){
            groups[groupingFunc(val)].push_back(val);
    } );
    return groups;
}

具有以下用途:

int main() {
    list<string> strs = {"hello", "world", "Hello", "World"};
    auto groupOfStrings =
        groupValues(strs.begin(), strs.end(), 
            [](auto& val) {
                return (char)toupper(val.at(0));
        });
    print(groupOfStrings); // assume a print method

    list<int> numbers = {1, 5, 10, 24, 13};
    auto groupOfNumbers =
        groupValues(numbers.begin(), numbers.end(), 
            [](int val) {
                int decile = int(val / 10) * 10;
                return to_string(decile) + '-' + to_string(decile + 9);
        });
    print(groupOfNumbers); // assume a print method
}

我对(过度?) - 在groupValues函数中使用 declval decltype 有点不情愿。

您是否看到了更好的写作方式?

(问题主要是为了更好的风格和清晰度,除非你看到任何其他问题)。

代码:http://coliru.stacked-crooked.com/a/f65d4939b402a750

1 个答案:

答案 0 :(得分:1)

我可能会在函数中移动最后两个模板参数,并使用std :: result_of来提供稍微整洁的函数:

template <typename T>
using deref_iter_t = std::remove_reference_t<decltype(*std::declval<T>())>;

template<class Iterator, class GroupingFunc>
auto groupValues(Iterator begin, Iterator end, GroupingFunc groupingFunc) {
    using T = deref_iter_t<Iterator>;
    using GroupingType = std::result_of_t<GroupingFunc(T&)>;
    std::map<GroupingType, std::list<T>> groups;
    std::for_each(begin, end, [&groups, groupingFunc](const auto& val){
        groups[groupingFunc(val)].push_back(val);
    });
    return groups;
}

live demo