c++ - 具有 C++11 构造的映射函数

标签 c++ templates c++11 visual-studio-2012 metaprogramming

既是为了自学实现比简单的基本模板构造更高级的模板构造,又因为它们在很多情况下都很有用,我正在尝试使用 c++11 构造来实现函数式编程中常见的映射、过滤器和类似函数,例如decltype.

我在创建我使用的编译器可以处理的函数原型(prototype)时遇到了问题,所以我不得不问你如何创建这样的东西:

//
// Takes an iterable, applies a function to every element, and returns a vector of the results
//
template <typename T, typename Func>
auto map(const T& iterable, Func func) -> std::vector< decltype(  func( *iterable.cbegin() ) ) >
{
    // body snipped
}

也就是说,这个函数应该接受任何可迭代对象和一个以可迭代对象值类型作为参数并返回某种值的函数。函数调用的结果将是一个 vector ,无论传入的 iterable 类型如何,传递的函数返回的类型如何。

map 函数应该接受任何具有有效原型(prototype)的函数作为参数,无论它是函数指针、仿函数还是 lambda 表达式。

将上面的函数与此测试代码结合使用:

std::vector<int> intVector;
intVector.push_back(1);
intVector.push_back(2);

map(intVector, [](int& value) { return value + 1; });

使 visual studio 吐出 C2893(“无法专门化函数模板”)错误,我不确定出了什么问题。

更新: 应用评论中建议的更改和到目前为止对问题的回答,测试了新原型(prototype)但仍然存在相同的错误。

最佳答案

这可能会如您所愿。它在内部使用 std::transform,它基本上完成了全部工作。我编写的函数只不过是一个简单的容器包装器(不适用于 C 风格的数组,这需要一些额外的类型特征):

#include <vector>
#include <algorithm>
#include <type_traits>

//
// Takes an iterable, applies a function to every element, 
// and returns a vector of the results
//
template <typename T, typename Func>
auto map_container(const T& iterable, Func&& func) ->
    std::vector<decltype(func(std::declval<typename T::value_type>()))>
{
    // Some convenience type definitions
    typedef decltype(func(std::declval<typename T::value_type>())) value_type;
    typedef std::vector<value_type> result_type;

    // Prepares an output vector of the appropriate size
    result_type res(iterable.size());

    // Let std::transform apply `func` to all elements
    // (use perfect forwarding for the function object)
    std::transform(
        begin(iterable), end(iterable), res.begin(),
        std::forward<Func>(func)
        );

    return res;
}

但是,请注意,您的 lambda 应该采用对 const 的引用,或者在 int 的情况下,最好按值来采用它的参数。

此外,我将函数从 map 重命名为 map_container:为函数、变量重用 C++ 标准库的标准容器名称是一种糟糕的编程习惯,或您程序中的任何其他内容。

对我来说,这给出了所需的输出:

#include <iostream>

int main()
{
    std::vector<int> intVector;

    intVector.push_back(1);
    intVector.push_back(2);

    auto v = map_container(intVector, [] (int value) { return value + 1; });

    for (int i : v) { std::cout << i << " "; }
}

关于c++ - 具有 C++11 构造的映射函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14945223/

相关文章:

c++ - 如何创建通用动态数组?

c++ - 我使用 C++ 标准库的 find 有什么问题?

c++ - 插入迭代器如何在 C++ 中工作

c++ - 清除终端的额外输入

c++ - 在没有 #define 的情况下捕获 __LINE__ 和 __FILE__

c++ - 有什么方法可以使此相对简单(嵌套在内存中)的C++代码更有效?

c++ - 什么时候分配 block 作用域变量

wpf - 无法通过类型(!)(wpf)找到模板化控件的父级

c++ - 添加 'constexpr' 可以改变行为吗?

c++ - 在预编译单元中定义宏条件语句是否明智?