Sid*_*gal 5 c++ templates c++11 std-function
我有一个函数应该返回与该函数相同类型的std ::函数.基本上我想要这样的东西:
using RetType = std::function<RetType(void)>;
Run Code Online (Sandbox Code Playgroud)
这显然不会编译.如何正确声明返回类型?
你不能用std::function
那种方式。
您可以自己推出,但这需要一些工作。
这是一个草图:
template<class T, class A, class B>
struct sub{using type=T;};
template<class T, class A, class B>
using sub_t=typename sub<T,A,B>::type;
template<class T, class B>
struct sub<T,T,B>{using type=B;};
template<class R,class...Args,class A,class B>
struct sub<R(Args...),A,B>{
using type=sub_t<R,A,B>(sub_t<Args,A,B>...);
};
Run Code Online (Sandbox Code Playgroud)
写出上面的内容。它接受一个类型T
,如果匹配则A
返回B
。否则返回T
。它也适用于函数签名。
我们可以将其与签名中的“标志”类型一起使用,以替换函数对象本身的类型:
struct recurse{}; // flag type
// not needed in C++14:
template<class Sig>
using result_of_t=typename std::result_of<Sig>::type;
template<class Sig>
struct func {
using Sig2=sub_t<Sig,recurse,func>;
using function = std::function<Sig2>;
function impl;
template<class...Ts>
result_of_t<function const&(Ts...)>
operator()(Ts&&...ts)const
{
return impl(std::forward<Ts>(ts)...);
}
};
Run Code Online (Sandbox Code Playgroud)
然后func<recurse()>
是一个函数对象,调用时返回一个func<recurse()>
.
事实证明,实现就像存储 astd::function<Sig2>
并调用它一样简单。上面的代码缺乏修饰——你需要构造函数、更多的运算符、隐私等等。
请注意,如果您想避免通过引用捕获自己的副本以便*this
在 lambda 中返回,则 y 组合器可能很有用,因为通过引用捕获意味着有限的生命周期(并避免使用共享 ptr)。
其他有用的工作将增强sub
处理对 的引用A
,甚至包含A
作为参数的模板。(一般的子算法在 C++ 中是不可行的,因为 C++ 没有完整的元模板功能,但是处理当前的每个模板类std
很容易:它们都是纯类型模板,或者std::array
)。
为了完整起见,您可以将其添加到sub
:
// optional stuff for completeness:
template<class T,class A,class B>
struct sub<T&,A,B>{
using type=sub_t<T,A,B>&;
};
template<class T,class A,class B>
struct sub<T*,A,B>{
using type=sub_t<T,A,B>*;
};
template<template<class...>class Z,class... Ts,class A,class B>
struct sub<Z<Ts...>,A,B>{
using type=Z<sub_t<Ts,A,B>...>;
};
template<template<class,size_t>class Z,class T,size_t n,class A,class B>
struct sub<Z<T,n>,A,B>{
using type=Z<sub_t<T,A,B>,n>;
};
template<class T,size_t n,class A,class B>
struct sub<T[n],A,B>{
using type=sub_t<T,A,B>[n];
};
template<class T,class A,class B>
struct sub<T[],A,B>{
using type=sub_t<T,A,B>[];
};
template<class T,class A,class B>
struct sub<T const,A,B>{
using type=sub_t<T,A,B> const;
};
template<class T,class A,class B>
struct sub<T volatile const,A,B>{
using type=sub_t<T,A,B> volatile const;
};
template<class T,class A,class B>
struct sub<T volatile,A,B>{
using type=sub_t<T,A,B> volatile;
};
Run Code Online (Sandbox Code Playgroud)
现在,它可以在许多模板、数组、引用和指针以及 cv 限定类型上递归地工作。这允许您编写如下内容:
func< std::vector<recurse>() >
Run Code Online (Sandbox Code Playgroud)
operator()
这是一个返回 a的函数对象func< std::vector<recurse>() >
。
请注意,这个过程并不十分完美,就好像some_template<recurse>
不是一个有效的模板实例化一样,上面的方法将不起作用。在这种情况下,需要使用可能应用的模板和参数的陌生版本进行替换,然后是应用程序。
归档时间: |
|
查看次数: |
1692 次 |
最近记录: |