返回返回std :: function的函数的类型

时间:2015-04-01 18:06:32

标签: c++ templates c++11 std-function

我有一个函数应该返回与该函数相同类型的std ::函数。基本上我想要这样的东西:

using RetType = std::function<RetType(void)>;

显然不会编译。如何正确声明返回类型?

1 个答案:

答案 0 :(得分:4)

你不能那样使用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>...);
};

写上面的内容。它需要T类型,如果它与A匹配,则返回B。否则返回T。它也适用于功能签名。

我们可以将此标记用于&#39;标记&#39;键入签名以替换函数对象本身的类型:

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)...);
  }
};

然后func<recurse()>是一个函数对象,在调用时返回func<recurse()>

结果实现就像存储std::function<Sig2>并调用它一样简单。上面的代码缺乏润色 - 你需要构造函数,更多操作符,隐私等等。

live example

请注意,如果您希望避免必须通过引用捕获自己的副本以便在lambda中返回*this,则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;
};

现在它可以在许多模板,数组,引用和指针以及cv限定类型上递归工作。这允许你写一些类似的东西:

func< std::vector<recurse>() >

是一个函数对象,operator()返回func< std::vector<recurse>() >

请注意,此过程并不完美,因为如果some_template<recurse>不是有效的模板实例化,则上述方法无法正常工作。一个采用可能应用的模板和参数的陌生人版本,在这种情况下是否需要替换,然后是应用程序。