将常规函数绑定到 std::function

Binding of regular function to std::function

本文关键字:std function 绑定 常规 函数      更新时间:2023-10-16

我正在尝试使用C++中的运算符重载对函数式组合进行编码,以便具有类似于函数式语言(例如Haskell(中的简单组合语法。我的目标是在合成中使用常规的裸C++函数。到目前为止,我编码了两个重载:

  1. operator%使用两个function<int(int)>参数和
  2. operator*使用模板类型作为参数。

operator%运行良好,但在main((中,我必须首先将常规函数包装到function<int(int)>operator%以便接受它们作为输入参数。我想通过将其迁移到使用模板参数的重载operator*来避免这个额外的步骤。我认为可以将常规函数绑定到 operator* 的模板参数,但编译器报告错误:

composingFunc.cpp11.cpp: In function ‘int main()’:
composingFunc.cpp11.cpp:28:12: error: invalid operands of types ‘int(int)’ and ‘int(int)’ to binary ‘operator*’
   cout<<(f*g)(5)<<endl;

您知道如何解决此问题吗?在operator*中使用模板参数不是强制性的 - 如果您有其他方法,只需在此处建议。

以下是源代码:

#include<iostream>
#include<functional>
using namespace std;
int f(int n)
{  return 2*n; }
int g(int n)
{  return n+1; }
function<int(int)> operator%(function<int(int)> f, function<int(int)> g)
{ 
  return [=](int x){ return f(g(x));};
}
template<typename T>
function<int(int)> operator*(const T &f, const T &g)
{
  function<int(int)> f1=f,f2=g; //this is encapsulated here so it is not
                                //necessary to repeat the same in main 
                                //for every functional composition
  return [=](int x){ return f1(f2(x));};
}
int main()
{
  function<int(int)> f1=f, f2=g; //I want to encapsulate this step into operator*
  cout<<(f1%f2)(5)<<endl; //this works well
  cout<<(f*g)(5)<<endl; //error in this line
}

编辑:Zac给出的解决方案使用类类型作为函数参数之一(根据标准,在运算符重载中使用至少一个枚举或类类型参数是强制性的(和一个模板类型参数。然后,常规C++函数很乐意绑定到这两个参数。因此,最终的运算符重载非常简单:

template<typename T>
function<int(int)> operator*(function<int(int)> f, T g)
{
    return [=](int x){ return f(g(x));};
}

然后可以使用简单的(f*g)(x)语法组合常规函数。

想到

的唯一想法是从一些假人开始:

struct F{}F;
function<int(int)> operator*(struct F, function<int(int)> g)
{
    return g;
}
function<int(int)> operator*(function<int(int)> f, function<int(int)> g)
{
    return [=](int x){ return f(g(x));};
}
int main()
{
    cout<<(F*f*g)(5)<<endl; // start with F, then add the real stuff
}

正如 Daniel 指出的,运算符重载中的一个参数必须是类或枚举类型。因此,需要实例化function<int(int)>f*g的调用,而不是函数指针类型。此问题有两种选择,

  1. 使用函数代替运算符,例如

    template<typename T>
    function<int(int)> multi(T x, T y)
    
  2. 将其中一个函数参数声明为"函数">

    template<typename T>
    function<int(int)> operator*(function<int(int)> x, T y)