我正在使用StreamsàlaJava 8的实现。我更喜欢编译器接受以下代码
Stream stream;
stream
.map ([] (int x) { return 10*x; }) // error
.forEach ([] (int x) { cout << x << " ";});
但编译器(gcc版本4.9.2)使用注释
拒绝它template argument deduction/substitution failed:
‘main(int, char**)::<lambda(int)>’ is not derived from ‘std::function<Re(int)>’
.map ([] (int x) { return 10*x; })
requires a type parameter for `map`
用
编译(并运行良好) .map<int> ([] (int x) { return 10*x; })
有没有希望摆脱<map>
的东西?
这是简化代码(具有足够的声明)
#include <iostream>
#include <functional>
using namespace std;
template <typename Tfrom, typename Tto> class MappedStream;
template <typename T>
class Stream
{
public:
void forEach(function< void(T) > action)
{}
template <typename Re>
MappedStream<T,Re> map (function < Re(T)> mapping) {
return MappedStream<T,Re>(*this, mapping);
}
};
template <typename Tfrom, typename Tto>
class MappedStream
: public Stream<Tto>
{
public:
MappedStream(Stream<Tfrom> & source,
function <Tto(Tfrom)> mapping)
{}
};
int main(int argc, char **argv)
{
Stream<int> stream;
stream
.map<int> ([] (int x) { return 10*x; })
// XXXXX <- how to get rid of this?
.forEach ([] (int x) { cout << x << " ";});
return 0;
}
答案 0 :(得分:4)
lambda不是std::function
,你几乎从不想要使用std::function</* something that contains a template parameter */>
作为函数模板的参数,因为模板参数的唯一方法就是推导出来的是调用者是否构造了一个std::function
并将其传入。
相反,接受任何函数对象,然后找出返回类型:
template <typename F, typename Re = std::result_of_t<F&(T)>>
MappedStream<T,Re> map (F mapping) {
return MappedStream<T,Re>(*this, mapping);
}
通常,应避免不必要的类型擦除。对于MappedStream
类型来说,不依赖于所使用的映射器是有用的,因此在内部存储std::function
是合理的,但forEach
可能应该是接受任何函数对象的模板,而不是而不仅仅是std::function
。