为了好玩,我尝试将std::transform
的使用尽可能接近map
in Haskell。
我目前的尝试看起来如下,但我想它可以做得更好。
#include <algorithm>
#include <iostream>
#include <iterator>
#include <vector>
using namespace std;
template<typename ContainerOut, typename ContainerIn, typename Functor>
ContainerOut mappHelp(const ContainerIn& xs, Functor op)
{
ContainerOut res;
res.reserve(xs.size());
transform(begin(xs), end(xs), back_inserter(res), op);
return res;
}
#define mapp(f, xs, res) mappHelp<decltype(res)>(xs, [](decltype(xs)::value_type it)f);
int main()
{
vector<int> xs = {1,2,3};
// How can we come closer to the following?
// auto ys = mapp({return it * 1.5;}, xs);
vector<double> ys = mapp({return it * 1.5;}, xs, ys);
copy(begin(ys), end(ys), ostream_iterator<double>(std::cout, ","));
}
关于如何摆脱必须告诉返回类型的一些想法(或者一般如何改进它)?
答案 0 :(得分:2)
您可以执行以下操作:
// helper class to rebind a container to use an other type
template<typename Container, typename T> struct rebind;
// specialization for vector
template <typename Tc, typename A, typename T>
struct rebind<std::vector<Tc, A>, T>
{
using type = std::vector<T, typename A::template rebind<T>::other>;
};
和你的方法
template<
typename F,
typename C,
typename ContainerOut =
typename rebind<C, decltype(std::declval<F>()(*std::begin(std::declval<C>())))>::type
>
ContainerOut
mapp(F f, const C& c)
{
ContainerOut res;
res.reserve(c.size());
std::transform(std::begin(c), std::end(c), std::back_inserter(res), f);
return res;
}