方便 技术 将你的lambda函数包装在一个 std::function 。由于它的构造函数是贪婪的,它会吸收任何可调用的东西,但是包装的增益会声明一个 的 显式类型 强>
std::function
auto f1 = [](double a, double b)->int { return a + b > 5.; // example function body }); std::function<int(double,double)> f2 ( [](double a, double b)->int { return a + b > 5.; // example function body };);
所以在上面的背景下 f1 面对你提到的问题,而 f2 的 是一个lambda 强> (在声明和使用它时保留了所有的便利),从某种意义上说,它没有“流浪类型”
f1
f2
首先,检测一个策略类 .step() :
.step()
namespace impl{ // eat a type and do nothing with it: template<typename T> struct type_sink { typedef void type; }; template<typename T> using TypeSink = typename type_sink<T>::type; // detect .step on T (T& means rvalue, T means lvalue, and T const& means const lvalue, etc) template<typename T, typename=void> struct has_step:std::false_type {}; template<typename T> struct has_step<T, TypeSink< decltype( std::declval<T>().step() ) > >: std::true_type {}; } template<typename T> struct has_step : impl::has_step<T> {};
所以现在我们有了 has_step<T> 这是特质类 true_type 如果 T 有个 .step() 方法可调用,和 false_type 除此以外。
has_step<T>
true_type
T
false_type
如果我们将它提供给函数,我们可以选择使用标记分派运行的实现:
template<typename T> return_type_whatever type_erase_helper( T&& t, std::true_type /* test passed */ ) { // branch 1 } template<typename T> return_type_whatever type_erase_helper( T&& t, std::false_type /* test failed */ ) { // branch 2 } template<typename T> return_type_whatever type_erase( T&& t ) { return type_erase_helper( std::forward<T>(t), has_step< typename std::decay<T>::type& >() ); }
如果你真的想根据具体来专门化一个特定的类 step 或不,您可以使用SFINAE技术。但是类型擦除不依赖于基于特化的类型擦除实现:我只是在生成类型擦除实现对象的函数上使用标记调度。
step
我们可以菊花链式这样的标签调度。另一个好的可能是 is_signature_compatible< T, R(Args...) > :
is_signature_compatible< T, R(Args...) >
namespace impl { template<typename T, typename Sig,typename=void> struct is_signature_compatible:std::false_type {}; template<typename T, typename R, typename... Args> struct is_signature_compatible< T, R(Args...), typename std::enable_if< std::is_convertible< typename std::result_of< T(Args...) >::type, R >::value >::type >:std::true_type {}; // dunno if this is needed? Possibly, and shouldn't hurt: template<typename T, typename... Args> struct is_signature_compatible< T, void(Args...), TypeSink< typename std::result_of< T(Args...) >::type > >:std::true_type {}; } template<typename T, typename Sig> struct is_signature_compatible:impl::is_signature_compatible<T,Sig> {};
然后,我们可以使用它来分离小麦从谷壳中的一个较小的“错误发生10递归 template 调用深刻的“方式。
template