在C++ 11中向向量添加map函数

Mat*_*her 4 c++ c++11

我有一个自定义矢量类,所有意图和目的就像std :: vector一样.我想添加一个简单的地图功能:

template <class T> class Vector
{
public:
    template<class mapFunction> Vector<typename mapFunction::result_type> map(mapFunction function)
    {
        Vector<mapFunction::result_type> result(_Length);
        for(UINT i = 0; i < _Length; i++)
        {
           result[i] = function(_Data[i]);
        }
        return result;
    }
    ...
}
Run Code Online (Sandbox Code Playgroud)

用法:

Vector<int> v(5);
for(int i = 0; i < 5; i++) v[i] = i;
auto mappedVector = v.map(function<double(int)>([](int a) { return a * 2.0; }));
Run Code Online (Sandbox Code Playgroud)

这有效,但我试图避免从lambda表达式转换为需要std::function.理想情况下,也只是v.map([](int a) { return a * 2.0; })); 我知道我大概可以写一个"make_function"类似"make_pair",以避免模板参数的需要,但你仍然需要转换所有的lambda表达式.

我把它转换为a std::function因为我不知道如何从原始lambda类型中提取返回类型; 因此我正在使用std::function::result_type.

我想下面的工作,但它不会 - 编译器只是抱怨说,它不能推导出模板参数为"返回类型":

template<class mapFunction, class returnType> Vector<returnType> Map2(mapFunction function)
{
    Vector<returnType> result(_Length);
    for(UINT i = 0; i < _Length; i++)
    {
        result[i] = function(_Data[i]);
    }
    return result;
}
Run Code Online (Sandbox Code Playgroud)

我意识到这样std::transform做(我可以通过调用轻松替换地图的主体std::transform),但我的问题实际上是用正确的方式来指定模板参数.

Mar*_*cia 10

首先,不要std::function用于这些问题.


我先给你举个例子,我会给你一个简短的解释.请注意,我使用a std::vector来存储数据并提供功能,因为我真的不想自己实现整个Vector类;).

现场工作代码

#include <iostream>
#include <vector>

//                /---------------------------------------------------------\
//                |                                                    //   |
template<typename T>                                                   //   |
class Vector {                                                         //   |
public:                                                                //   |
    std::vector<T> data;                                               //   |
                                                                       //   |
    template<class mapFunction>                                        //   |
    // Below: use C++11 trailing return type                                |
    auto map(mapFunction function) -> Vector<decltype(function(std::declval<T>()))>
    //                                       |                                   |
    {   //                                   |                                   |
        //                                   \-----------------------------------/
        //                                          |
        //                                          |
        //                 /-----------------------------------\
        //                 |                                   |
        using ReturnType = decltype(function(std::declval<T>()));

        Vector<ReturnType> result;

        auto size = data.size(); 
        result.data.reserve(size);

        for(std::size_t i = 0; i < size; i++)
        {
           result.data.push_back(function(data[i]));
        }

        return result;
    }
};

int main() {
    Vector<int> v;
    for(int i = 0; i < 10; ++i) {
        v.data.push_back(i);
    }

    auto newV = v.map([](int i) -> float {
        return (i * 2.0f) + 0.5f;       // Multiply by 2 and add 0.5
    });

    for(auto e : newV.data) {
        std::cout << e << std::endl;
    }
}
Run Code Online (Sandbox Code Playgroud)

首先,它使用C++ 11的尾随返回类型功能.它需要以这种方式完成,因为我们需要引用参数function.这decltype(function(std::declval<T>()))部分是有趣的人.在那,我们基本上问编译器

" function给定类型的参数值的返回类型是T什么?"

然后编译器给出返回类型,这就是我们给结果的第一个参数Vector.

后面的部分与你的相同,虽然我修改了它们的正确性和优雅.

请注意,在C++ 14中,您可以删除尾随返回类型,然后执行此操作

template<class mapFunction>
auto map(mapFunction function) {
   using ReturnType = decltype(function(std::declval<T>()));
   Vector<ReturnType> result;

   ...

   return result;
}
Run Code Online (Sandbox Code Playgroud)

  • +1花时间不仅提供解决方案,还绘制所有ASCII艺术图将部分链接在一起! (2认同)