0

I'm implementing Python's map in C++ (in a more functional way than std::transform):

#include <iostream>
#include <vector>
#include <functional>

template <typename TypeOut, typename TypeIn>
std::vector<TypeOut> fmap(std::function<TypeOut(const TypeIn&)> func, const std::vector<TypeIn>& vec) {
    std::vector<TypeOut> result;
    std::transform(vec.begin(), vec.end(),
                   std::back_inserter(result),
                   func);
    return std::move(result);
}

int main() {
    std::vector<int> vec_test;
    vec_test.push_back(1);
    vec_test.push_back(2);
    vec_test.push_back(3);

    std::function<int(const int&)> f = [](const int& x) {return x*x;};
    auto squared = fmap(f, vec_test);

    for (const auto& x: squared) {
        std::cout<<x<<" ";
    }
    std::cout<<std::endl;

    return 0;
}

This program is working, but it annoys me to manually set the type for std::function in:

std::function<int(const int&)> f = [](const int& x) {return x*x;};

How do I make compiler inference the type for me so that I could have

auto f = [](const int& x) {return x*x;};
auto squared = fmap(f, vec_test);

or even simpler:

auto squared = fmap([](const int& x) {return x*x;}, vec_test);

Rahn
  • 4,787
  • 4
  • 31
  • 57
  • 1
    One way is not to use a std::function a argument, but a simple template, and deduce the return type with auto. – gerum May 26 '21 at 12:24
  • It may be an artifact of reducing real-world code to a minimal example, but the use of `std::function` here is entirely gratuitous. That lambda is already a function that takes `const int&` and returns `int`; there's no need to coerce it to that type. `auto f = [](const int&x) { return x*x; }` would work just fine. As would skipping `f` and just calling `fmap` with that lambda as the first argument. – Pete Becker May 26 '21 at 12:49
  • One recommendation: you don't have to use `std::function` to write higher-order functions in C++! If you make the `func` argument to `fmap` a bare template parameter, then `fmap` will be able to directly take lambda functions without the `std::function` wrapper – hegel5000 May 26 '21 at 13:27
  • @hegel5000 Could you elaborate? – Rahn May 26 '21 at 14:09
  • 1
    Try this one template auto fmap(F func, const std::vector& vec) { TypeIn x; using TypeOut = decltype(func(x)); std::vector result; std::transform(vec.begin(), vec.end(), std::back_inserter(result), func); return std::move(result); } – nhatnq May 27 '21 at 05:09

0 Answers0