2

我正在尝试使用 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)语法组合常规函数。

4

2 回答 2

3

想到的唯一想法是从一些虚拟开始:

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
}
于 2013-10-10T21:57:34.853 回答
2

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

  1. 使用函数而不是运算符,例如

    template<typename T>
    function<int(int)> multi(T x, T y)
    
  2. 将函数参数之一声明为`function

    template<typename T>
    function<int(int)> operator*(function<int(int)> x, T y)
    
于 2013-10-10T22:23:05.030 回答