6

As a small exercise in functional programming in C++, I want to overload the operator* to allow me to compose 2 functions.

What stumps me is that if I define my operator like this:

std::function<float(float)> operator*(std::function<float(float)> func1, std::function<float(float)> func2)
{
   // ...
}

I cannot use it with regular functions as in:

float f(float);
float g(float);
auto composite = f*g;

Because I get:
error: invalid operands of types ‘float(float)’ and ‘float(float)’ to binary ‘operator*’

If I try to add a function pointer only version as in:

std::function<float(float)> operator*(float(*func1)(float) , float(*func2)(float))
{
   return [func1, func2](float x) { return func1(func2(x)); };
}

I get this error:
error: ‘std::function<float(float)> operator*(float (*)(float), float (*)(float))’ must have an argument of class or enumerated type

I was able to get it to work by adding a make_function helper, but that really makes the code ugly.

Is there a way to get this operator to automatically cast functions to std::function instances?

Community
  • 1
  • 1
Adi Shavit
  • 16,743
  • 5
  • 67
  • 137
  • Though this is a good question and the answer is also valuable, I would prefer to rename `operator*()` to something like `compose()` for clarity. Overriding operators with clear semantics is a hard thing to do, and will rarely be intuitive for the users. Just for sake of saving a bit of typing it's not worth it IMHO. – πάντα ῥεῖ Jun 01 '14 at 19:57
  • @πάνταῥεῖ: I agree in principle, but in this case: (1) it is a small experiment in functional C++ programming; (2) `operator*` does _not_ have clear semantics for functions, except, maybe, as functional composition. – Adi Shavit Jun 02 '14 at 05:51

1 Answers1

5

Unfortunately, C++ does not allow operators to be overloaded for built-in types. Just as you cannot implement your own operator* for two ints, you cannot implement it for two function pointers, except if you represent these functions with the std::function type which is a class and therefore not a built-in type.

You can, however, instead of using an operator, simply use a function:

std::function<float(float)> dot(float(*func1)(float) , float(*func2)(float))
{
   return [func1, func2](float x) { return func1(func2(x)); };
}
yizzlez
  • 8,757
  • 4
  • 29
  • 44
bitmask
  • 32,434
  • 14
  • 99
  • 159
  • That's unfortunate, but remember that I actually wanted to overload on `std::function<>` but, it seems that, beyond what you write, the overload mechanism does not perform the automatic conversion. – Adi Shavit Jun 02 '14 at 05:58
  • @AdiShavit: Not it wont. But you can create a wrapper that transforms a `float(*)(float)` into an `::std::function<...>`. – bitmask Jun 02 '14 at 09:38
  • Indeed. As I said in the original question, it does work with a such a conversion wrapper. – Adi Shavit Jun 02 '14 at 11:18