模板,类型演绎不足
templates, insufficient type deduction
我正在玩Streams的一个Java 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;
}
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
。
相关文章:
- 为什么 std::array 的演绎指南不允许不同的类型?
- 类型演绎 C++ 标准和自动
- λ类型演绎失败
- decltype(auto) 类型演绎:返回 x 与返回 (x)
- 使用decltype的动态多态类型演绎
- 普遍类型演绎scott-meyers
- c++ 11使用std::函数进行类型演绎
- 使用通用引用时进行类型演绎
- c++如何在无法进行类型演绎时调用模板化构造函数
- 函数模板中返回类型的模板实参演绎
- c#泛型中的类型演绎类似于c++模板
- 类型演绎不适用于std::function
- 为什么decltype返回类型在递归模板中失败,而返回类型演绎却工作得很好?
- 表达式模板中的按引用捕获可以与类型演绎共存
- 类型演绎模板函数c++
- 模板,类型演绎不足
- 用演绎的类型公开类成员函数
- 括号初始化列表和函数模板类型演绎顺序
- 在模板演绎中保持函数指针形参的完整类型
- c++类型强制演绎