假设我想在C++中实现一个通用的高阶Map
函数。 Map
应带一个容器和一个转换函数,并返回一个相同类型的容器,但可能使用不同类型的项目。模板类型的约束
让我们vector
例如:
template <typename InT, typename OutT, typename Tr>
vector<OutT> Map(vector<InT> cont, Tr tr)
{
OutCont out(cont.size());
auto oit = out.begin();
for (auto it = cont.cbegin(); it != cont.cend(); ++it, ++ot)
{
*oit = tr(*it);
}
}
,我想用这样的:
vector<int> v(10);
std::iota(v.begin(), v.end(), 0);
auto x = Map(v, [](int x) -> int {return x * 2;});
这种失败在VC++ 2012,给我下面的错误:
error C2783: 'std::vector<OutT> Map(std::vector<_Ty>,Tr)' : could not deduce template argument for 'OutT'
在我看来,编译器具有所有必要的信息,因为我明确定义lambda中的返回类型。有没有解决的办法?
上述示例使用vector
。有没有办法使用泛型类型,以便输入和输出类型相同?例如,如果我有一个输入容器定义为vector<string>
和转换函数tr(string a) -> int
,那么我的目标是让编译器找出输出类型为vector<int>
。下面是伪代码为我想要实现:输出类型推断
template <typename InT, typename Tr>
auto Map(std::vector<InT> cont, Tr tr) -> std::vector<decltype(tr(cont[0]))>
{
std::vector<decltype(tr(cont[0]))> out(cont.size());
auto oit = out.begin();
for (auto it = cont.cbegin(); it != cont.cend(); ++it, ++oit)
{
*oit = tr(*it);
}
return out;
}
:
template <typename Cont<InT>, typename Cont<OutT>, typename Tr<InT, OutT>>
Cont<OutT> Map(Cont<InT> cont, Tr<InT, OutT> tr)
{
// Implementation
}
无关,但命名您的函数'map'比较混乱,给出'std :: map'。 – juanchopanza
函数式编程'map' =='std :: transform'。迭代器真的可以让你在C++中通过容器进行泛型编程:使用它们。 – Yuushi
谢谢。我将它改为'Map'。应该消除混淆。 – Max