繁体   English   中英

递归typedef函数定义:std :: function返回自己的类型

[英]Recursive typedef function definition : std::function returning its own type

我正在尝试实现一个状态机。 状态由callback_t类型的函数表示: callback_t(int&) ,它返回相同类型的函数。

我不知道如何实现它,因为似乎不允许递归类型函数。

在这里我尝试(作为玩具):

#include <stdio.h>
#include <functional>

typedef std::function< callback_t(int &) > callback_t ;
callback_t f1(int & i)
{
    i++;
    return f1;
}
callback_t f0(int & i)
{
    if(i==0) i++;
    return f1;
}
callback_t start(int & i)
{
    i=0;
    return f0;
}


int main(int argc, char **argv)
{
    callback_t begin = start;
    int i=0;

    while(i<100)
        begin = begin(i);

    printf("hello world\n");
    return 0;
}

错误:

C:/work/tests/tests/main.cpp:4:41: error: 'callback_t' was not declared in this scope
typedef std::function< callback_t(int &) > callback_t ;
                                       ^

有没有办法实现这种行为?

环境:win7,codelite,mingw 4.8.1

由于无法进行递归类型定义,因此可以声明一个包含该函数并隐式转换为该函数的结构:

template< typename... T >
struct RecursiveHelper
{
    typedef std::function< RecursiveHelper(T...) > type;
    RecursiveHelper( type f ) : func(f) {}
    operator type () { return func; }
    type func;
};

typedef RecursiveHelper<int&>::type callback_t;

示例: http//coliru.stacked-crooked.com/a/c6d6c29f1718e121

一种用于将一种类型替换为另一种类型的小型库:

template<class T>struct tag{using type=T;};

template<class X, class A, class B> struct subst:tag<X>{};
template<class X, class A, class B>
using subst_t=typename subst<X,A,B>::type;

template<class A, class B> struct subst<A,A,B>:tag<B>{};
template<class X, class A, class B>
struct subst<X&,A,B>:tag<subst_t<X,A,B>&>{};
template<class X, class A, class B>
struct subst<X&&,A,B>:tag<subst_t<X,A,B>&&>{};
template<class X, class A, class B>
struct subst<X const,A,B>:tag<subst_t<X,A,B>const>{};
template<class X, class A, class B>
struct subst<X volatile,A,B>:tag<subst_t<X,A,B>volatile>{};
template<class X, class A, class B>
struct subst<X const volatile,A,B>:tag<subst_t<X,A,B>const volatile>{};
template<template<class...>class Z,class...Xs, class A, class B>
struct subst<Z<Xs...>,A,B>:tag<Z<subst_t<Xs,A,B>...>>{};
template<template<class,size_t>class Z,class X,size_t n, class A, class B>
struct subst<Z<X,n>,A,B>:tag<Z<subst_t<X,A,B>,n>>{};
template<class R,class...Xs, class A, class B>
struct subst<R(Xs...),A,B>:tag<subst_t<R,A,B>(subst_t<Xs,A,B>...)>{};

现在我们用它:

struct own_type {};

template<class Sig>
struct recursive_func{
  using func=std::function< subst_t<Sig, own_type, recursive_func> >;
  template<class...Ts>
  std::result_of_t<func const&(Ts...)>
  operator()(Ts&&...ts)const{
    return f(std::forward<Ts>(ts)...);
  }
  operator func const&()const&{return f;}
  operator func&()&{return f;}
  operator func()&&{return std::move(f);}
  template<class F,
    class=std::enable_if_t<
      !std::is_same<recursive_func,std::decay_t<F>>::value
      && std::is_convertible<F,func>::value
    >
  >
  recursive_func(F&&fin):f(fin){}

  func* operator->(){return f;}
  func const* operator->()const{return f;}
private:
  func f;
};

这给你一个可爱的语法:

recursive_func< std::vector<own_type>() > f;

是一个返回自己类型的向量的函数。

这使用了一些C ++ 14 _t别名。 如果你的编译器是严格的C ++ 11, std::blah_t<?>可以用typename std::blah<?>::type替换。 可能还有其他错别字。

缺点是,当使用own_type时,期望其类型满足直接上下文中的某些属性的模板可能会失败。 这可以固定与延迟模板敷贴subst理解,但在不经意的使用是不太可能是一个问题。

实例

typedef std::function< callback_t(int &) > callback_t ;
                       **********

您尝试使用定义本身定义新类型。 这是不可能的! 在定义之前不能使用callback_t。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM