用于函数对象更改参数和返回值类型的包装器 我想编写C++类(让类型名称为适配器),它接受构造函数中的函数指针或函数对象(特别是lambda函数),并通过内部值(如STD::EngultExpPL函数)来存储它。在构建类之后,它也表示函数对象,并充当内部函数对象的包装器。但有以下条件: 包装类(适配器)的返回类型始终是预定义的(让它成为ReturnType) 但内部函子可能并没有返回值——在本例中,某些DefaultValue被替换 包装器类始终接收一些ArgType作为运算符()的参数 但内部函数也可以接收ArgType作为参数,或者可能根本不接受参数——在后一种情况下,只应在不带参数的情况下调用它

用于函数对象更改参数和返回值类型的包装器 我想编写C++类(让类型名称为适配器),它接受构造函数中的函数指针或函数对象(特别是lambda函数),并通过内部值(如STD::EngultExpPL函数)来存储它。在构建类之后,它也表示函数对象,并充当内部函数对象的包装器。但有以下条件: 包装类(适配器)的返回类型始终是预定义的(让它成为ReturnType) 但内部函子可能并没有返回值——在本例中,某些DefaultValue被替换 包装器类始终接收一些ArgType作为运算符()的参数 但内部函数也可以接收ArgType作为参数,或者可能根本不接受参数——在后一种情况下,只应在不带参数的情况下调用它,c++,c++11,templates,C++,C++11,Templates,第一个问题——这在C++11中是可能的,第二个问题是我如何做到这一点?我不知道从哪里开始 我需要推断(在模板中)函数对象的返回值?第一个陷阱是std::result_不支持函数指针。我不知道如何为函数对象推断参数类型(可能为空、无参数或ArgType)(我知道如何通过模板结构为函数指针推断参数类型,但如何为函数对象推断参数类型?) 我需要这样的东西: template <typename Functor?> class Adapter { private: std::func

第一个问题——这在C++11中是可能的,第二个问题是我如何做到这一点?我不知道从哪里开始

我需要推断(在模板中)函数对象的返回值?第一个陷阱是std::result_不支持函数指针。我不知道如何为函数对象推断参数类型(可能为空、无参数或ArgType)(我知道如何通过模板结构为函数指针推断参数类型,但如何为函数对象推断参数类型?)

我需要这样的东西:

template <typename Functor?> class Adapter
{
private:
    std::function<Void_or_ReturnType (Void_or_ArgType)> f;

public:
    template <typename Functor?> Adapter(const Functor& f) { ??? }

    ReturnType operator()(ArgType arg)
    {
         // one of the following four variants:
         return f(arg);
         f(arg); return DefaultValue;
         return f();
         f(); return DefaultValue;
  }
};
模板类适配器
{
私人:
std::函数f;
公众:
模板适配器(常量函子&f){???}
ReturnType运算符()(ArgType arg)
{
//以下四种变体之一:
返回f(arg);
f(arg);返回DefaultValue;
返回f();
f();返回DefaultValue;
}
};

可能我需要推导模板中的Void_或_ReturnType和Void_或_ArgType类型,并为运算符()编写不同的模板专门化,这四种情况各有不同。但我究竟如何才能做到这一点呢?

我花了几个小时在这方面,并找到了一些解决方案:

不确定,这是否是一个好的解决方案。可能有人建议我,我怎样才能最小化这个代码

我在这里复制源代码以防万一(我在coliru.stacked-crooked.com上更新了源代码,这里是旧版本,请参阅上面的链接):

#包括
#包括
//函子
模板结构IsArgs{typedef typename IsArgs::type;};
模板结构IsResult{typedef typename IsResult::type;};
//函数指针
模板结构IsArgs{typedef Yes type;};
模板结构IsArgs{typedef No type;};
模板结构IsResult{typedef Yes type;};
模板结构IsResult{typedef No type;};
//对于函数引用
模板结构IsArgs{typedef Yes type;};
模板结构IsArgs{typedef No type;};
模板结构IsResult{typedef Yes type;};
模板结构IsResult{typedef No type;};
//用于成员指针(lambdas、函子)
模板结构IsArgs{typedef Yes type;};
模板结构IsArgs{typedef No type;};
模板结构IsResult{typedef Yes type;};
模板结构IsResult{typedef No type;};
模板类适配器
{
结构Noargs{
std::函数func;
模板Noargs(常数F&F):func(F){}
Retval运算符()(Args…{return func();}
};
结构Noreturn{
std::函数func;
模板Noreturn(常数F&F):func(F){}
Retval运算符()(Args…Args){return func(Args…,默认;}
};
结构NORETAGS{
std::函数func;
模板Noretargs(常数F&F):func(F){}
Retval运算符()(Args…{return func(),默认;}
};
std::函数func;
公众:
模板适配器(常量函子&f)
:func(typename IsArgs::type(f)){}
Retval运算符()(Args…Args)常量{return func(Args…;}
};
void dead_silent_f(){put(“dead/silent”);}
void silent_f(const char*arg){printf(“silent%s\n”,arg);}
const char*dead_f(){puts(“dead”);返回“dead”;}
常量字符*normal\u f(常量字符*arg){printf(“normal%s\n”,arg);返回“normal”}
常量字符默认值[]=“默认值”;
int main(int argc,char*argv[])
{    
类型定义适配器A;
{
puts(“函数引用”);
A ds(聋哑);printf(“->%s\n”,ds(“ds”);
A s(无声);printf(“->%s\n”,s(“s”));
A d(聋子);printf(“->%s\n”,d(“d”);
A n(正常);printf(“->%s\n”,n(“n”);
认沽权(“”);
}
{
puts(“函数指针”);
一个ds(&dead\u silent\u f);printf(“->%s\n”,ds(“ds”));
A s(&silent);printf(“->%s\n”,s(“s”));
A d(&d);printf(“->%s\n”,d(“d”);
A n(&normal);printf(“->%s\n”,n(“n”));
认沽权(“”);
}
{
看跌期权(“函子”);
一个ds([=]{printf(“聋哑/无声的%d\n”,argc);});printf(“->%s\n”,ds(“ds”);
A s([=](常量字符*A){printf(“静默(%s)%d\n”,A,argc);});printf(“->%s\n”,s(“s”));
A d([=]{printf(“聋子%d\n”,argc);返回“聋子”});printf(->%s\n,d(“d”);
A n([=](常量字符*A){printf(“正常(%s)%d\n”,A,argc);返回“正常”});printf(->%s\n),n(“n”);
}
返回0;
}

嗯。。。你问的并不是那么简单

首先:我认为将默认返回值作为模板参数不是一个好主意:适用于整数类型,但例如,不适用于浮点类型。您可以绕过这个问题,但我建议将默认值作为值传递到构造函数中

第二:我建议使用以下代码来检测
F
id类型的可调用对象是否可以使用给定的类型列表进行调用

template <typename ...>
constexpr std::false_type isInvocableWithHelper (long);

template <typename F, typename ... Args>
constexpr auto isInvocableWithHelper (int)
   -> decltype( std::declval<F>()
                   (std::forward<Args>(std::declval<Args>())...),
                std::true_type{} );

template <typename F, typename ... Args>
using isInvocableWith = decltype(isInvocableWithHelper<F, Args...>(0));
其中,只有当
F
对象可通过
Args…
对象和
  template <typename F>
  Adapter (F const & f, RetT defVal = RetT{})
     : Adapter{f, defVal, isInvocableWith<F, Args...>{},
               isInvocableWith<F>{}}
   { }
  template <typename F>
  Adapter (F const & f, RetT const & defVal, std::true_type const &,
           std::false_type const &)
   : Adapter{f, defVal, std::true_type{}, std::false_type{},
             std::is_same<void,
                decltype(f(std::forward<Args>(std::declval<Args>())...))>{}}
   { } 
  template <typename F>
  Adapter (F const & f, RetT const & defVal, std::false_type const &,
           std::true_type const &)
   : Adapter{f, defVal, std::false_type{}, std::true_type{},
             std::is_same<void, decltype(f())>{}}
   { }
  template <typename F>
  Adapter (F const & f, RetT const & defVal, std::true_type const &,
           std::false_type const &, std::true_type const &)
     : defV{defVal}
   {
     func = [&, this](Args && ... as)
      { f(std::forward<Args>(as)...); return defV; };

     std::cout << "--- case 1 (full, void)" << std::endl;
   }

  template <typename F>
  Adapter (F const & f, RetT const &, std::true_type const &,
           std::false_type const &, std::false_type const &)
   {
     func = [&](Args && ... as)
      { return f(std::forward<Args>(as)...); };

     std::cout << "--- case 2 (full, RetT)" << std::endl;
   }

  template <typename F>
  Adapter (F const & f, RetT const & defVal, std::false_type const &,
           std::true_type const &, std::true_type const &)
     : defV{defVal}
   {
     func = [&, this](Args && ...)
      { f(); return defV; };

     std::cout << "--- case 3 (noArgs, void)" << std::endl;
   }

  template <typename F>
  Adapter (F const & f, RetT const &, std::false_type const &,
           std::true_type const &, std::false_type const &)
   {
     func = [&](Args && ...)
      { return f(); };

     std::cout << "--- case 4 (noArgs, RetT)" << std::endl;
   }
#include <cstdio>
#include <iostream>
#include <functional>

template <typename ...>
constexpr std::false_type isInvocableWithHelper (long);

template <typename F, typename ... Args>
constexpr auto isInvocableWithHelper (int)
   -> decltype( std::declval<F>()
                   (std::forward<Args>(std::declval<Args>())...),
                std::true_type{} );

template <typename F, typename ... Args>
using isInvocableWith = decltype(isInvocableWithHelper<F, Args...>(0));

template <typename RetT, typename ... Args>
class Adapter
 {
   private:
      std::function<RetT(Args ...)> func;

      RetT  defV { RetT{} };

      template <typename F>
      Adapter (F const & f, RetT const & defVal, std::true_type const &,
               std::false_type const &, std::true_type const &)
         : defV{defVal}
       {
         func = [&, this](Args && ... as)
          { f(std::forward<Args>(as)...); return defV; };

         std::cout << "--- case 1 (full, void)" << std::endl;
       }

      template <typename F>
      Adapter (F const & f, RetT const &, std::true_type const &,
               std::false_type const &, std::false_type const &)
       {
         func = [&](Args && ... as)
          { return f(std::forward<Args>(as)...); };

         std::cout << "--- case 2 (full, RetT)" << std::endl;
       }

      template <typename F>
      Adapter (F const & f, RetT const & defVal, std::false_type const &,
               std::true_type const &, std::true_type const &)
         : defV{defVal}
       {
         func = [&, this](Args && ...)
          { f(); return defV; };

         std::cout << "--- case 3 (noArgs, void)" << std::endl;
       }

      template <typename F>
      Adapter (F const & f, RetT const &, std::false_type const &,
               std::true_type const &, std::false_type const &)
       {
         func = [&](Args && ...)
          { return f(); };

         std::cout << "--- case 4 (noArgs, RetT)" << std::endl;
       }

      template <typename F>
      Adapter (F const & f, RetT const & defVal, std::true_type const &,
               std::false_type const &)
       : Adapter{f, defVal, std::true_type{}, std::false_type{},
                 std::is_same<void,
                    decltype(f(std::forward<Args>(std::declval<Args>())...))>{}}
       { } 

      template <typename F>
      Adapter (F const & f, RetT const & defVal, std::false_type const &,
               std::true_type const &)
       : Adapter{f, defVal, std::false_type{}, std::true_type{},
                 std::is_same<void, decltype(f())>{}}
       { }

   public:
      template <typename F>
      Adapter (F const & f, RetT defVal = RetT{})
         : Adapter{f, defVal, isInvocableWith<F, Args...>{},
                   isInvocableWith<F>{}}
       { }

      template <typename ... As>
      RetT operator() (As && ... as) const
       { return func(std::forward<As>(as)...); }
 };

void deaf_silent_f ()
 { puts("deaf/silent"); }

void silent_f (char const * arg)
 { printf("silent %s\n", arg); }

char const * deaf_f ()
 { puts("deaf"); return "deaf"; }

char const * normal_f (char const * arg)
 { printf("normal %s\n", arg); return "normal"; }

int main ()
 {    
   typedef Adapter<char const *, char const *> A;

    {
      puts("function refs");
      A ds(deaf_silent_f, "Def1"); printf("-> %s\n", ds("ds"));
      A s(silent_f, "Def2"); printf("-> %s\n", s("s"));
      A d(deaf_f); printf("-> %s\n", d("d"));
      A n(normal_f); printf("-> %s\n", n("n"));
      puts("");
    }

    {
      puts("function pointers");
      A ds(&deaf_silent_f, "Def3"); printf("-> %s\n", ds("ds"));
      A s(&silent_f, "Def4"); printf("-> %s\n", s("s"));
      A d(&deaf_f); printf("-> %s\n", d("d"));
      A n(&normal_f); printf("-> %s\n", n("n"));
      puts("");
    }

    {
      puts("functors");
      A ds([=]{ printf("deaf/silent %d\n", 42); }, "Def5");
      printf("-> %s\n", ds("ds"));
      A s([=](char const * a){ printf("silent(%s) %d\n", a, 42); }, "Def6");
      printf("-> %s\n", s("s"));
      A d([=]{ printf("deaf %d\n", 42); return "deaf"; });
      printf("-> %s\n", d("d"));
      A n([=](char const * a){ printf("normal(%s) %d\n", a, 42);
                               return "normal";});
      printf("-> %s\n", n("n"));
    }
 }