Function Composition Operator - c++

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?

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)); };
}

Related

Making one user defined conversion function preferred over another

I am trying to write a simple class that will act as a complex<double> number when used in a context that warrants a complex number, otherwise it will act as a double (with the requirement that the imaginary part must be 0 when used this way)
This is what I have so far:
class Sample
{
public:
Sample() {}
Sample(double real) : m_data(real) {}
Sample(double real, double imaginary) : m_data(real, imaginary) {}
operator std::complex<double>() const
{
return m_data;
}
operator double() const
{
assert(m_data.imag() == 0.0);
return m_data.real();
}
private:
std::complex<double> m_data;
};
This works great for most situations. Anytime this class is passed to a function that expects a complex number it will act as though it is a complex number. Anytime it is passed to a function that expects a double it will act as though it is a double.
The problem arises when I pass it to a function that will accept BOTH complex numbers and doubles. (for example std::arg). When I try to pass a Sample object to std::arg it doesn't know which conversion to use since both are technically valid.
In situations like this I want the complex conversion to be "preferred" and have it just pass it as a complex. Is there any way to make one user defined function preferred over another when both conversions would be technically acceptable?
I think in general it is impossible to write one conversion operator that will always be preferred to another conversion operator in the same class.
But if you need just to call std::arg with the argument of your class, then it already behaves as you expect preferring std::complex<double> over double:
#include <complex>
#include <iostream>
struct S {
operator std::complex<double>() const {
std::cout << "std::complex<double>";
return 2;
}
operator double() const {
std::cout << "double";
return 2;
}
};
int main() {
S s;
//(void)std::arg(s); //error: cannot deduce function template parameter
(void)std::arg<double>(s);
}
The program compiles and prints std::complex<double>. Demo: https://gcc.godbolt.org/z/dvxv17vvz
Please note that the call std::arg(s) is impossible because template parameter of std::complex<T> cannot be deduced from s. And std::arg<double>(s) prefers std::complex overload in all tested implementations of the standard library.

Why is this user-defined conversion not done?

Consider:
template<typename T>
struct Prop
{
T value;
operator T() { return value; }
};
int main()
{
Prop<float> p1 { 5 };
Prop<std::vector<float>> p2 { { 1, 2, 3 } };
float f1 = p1; // Works fine
float f2_1_1 = p2.value[0]; // Works fine
float f2_1_2 = p2[0]; // Doesn't compile
return 0;
}
Why doesn't the line marked as such compile? Shouldn't it perform implicit conversion using the supplied conversion operator into std::vector<>, so that the [] can be found?
There are (many) other questions on this site that ask variations on this question, but I couldn't find one that I think applies here. Does it have to do with std::vector being a template?
Implicit conversions are not considered for objects of member function calls, including the subscript operator overload.
Consider the consequences if that were allowed: Every single time any undeclared member function is called like this, the compiler would have to figure out all the types that the object can be converted to (note that any other otherwise unrelated type could have a converting constructor), and check if that has declared the missing member function. Not to mention how confusing that would be for the reader of the code (the conversion might be obvious in your conversion operator case, but not in the converting constructor case, and as far as I know, they are not otherwise treated differently).
So is there a notationally convenient way to get Prop to behave the way I want
You would have to define a member function for each of the member function of vector that you want to pass pass through transparently. Here is the subscript operator as an example:
auto operator[](std::size_t pos) {
return value[pos];
}
auto operator[](std::size_t pos) const {
return value[pos];
}
The problem is of course that all wrapped member functions must be explicitly declared. Another problem is arguments whose type depend on T. For example, vector::operator[] uses vector::size_type, which might not be defined for all T that you might use (certainly not for float). Here we make a compromise and use std::size_t.
A less laborious way of creating such "transparent" wrapper is inheritance. A publicly inheriting template would automatically have all the member functions of the parent and be implicitly convertible to it and can be referred by pointers and references of parent type. However, the transparency of such approach is a bit problematic mainly because ~vector is not virtual.
Private inheritance allows same wrapping as your member approach, but with much nicer syntax:
template<typename T>
struct Prop : private T
{
using T::operator[];
using T::T;
};
Note that inheritance approach prevents you from using fundamental types as T. Also, it makes the implicit conversion impossible (even with conversion operator) , so you cannot use Prop as T in free functions that expect T.
PS. Note that your conversion operator returns a value, so the vector must be copied, which may be undesirable. Consider providing reference versions instead:
operator T&&()&& { return *this; }
operator T&()& { return *this; }
operator const T&() const& { return *this; }
the same way that any of the
p2.size();
p2.begin();
p2.push_back(24);
// etc.
don't make sense to compile
also
p2[0];
which is equivalent with
p2.operator[](0);
doesn't make sense to compile\
If you want this behavior (i.e. for Prop<T> to borrow T members) there is a C++ proposal by Bjarne to add the dot operator to the language. I would work the same way that operator -> works for smart pointers. AFAIR it had a lot of controversy and so I wouldn't hold my breath for it.
A bit of background for the operator dot proposal—Bjarne Stroustrup
Operator Dot (R3) - Bjarne Stroustrup, Gabriel Dos Rei
Smart References through Delegation: An Alternative to N4477's Operator Dot - Hubert Tong, Faisal Vali
Alternatives to operator dot - Bjarne Stroustrup

Conversion from my class to int

I am using a library that is templated and that I do not wish to modify. Namely CImg.
This library has been mostly designed to work with templates of simple types: float, double, int etc.
At some point, this library does:
CImg<T>& fill(const T val) {
if (is_empty()) return *this;
if (val && sizeof(T)!=1) cimg_for(*this,ptrd,T) *ptrd = val;
else std::memset(_data,(int)val,size()*sizeof(T));
return *this;
}
Now I want to use this library with a more complex class as template parameter. My particular class is such that sizeof(T)!=1 and most of the time, the fill function will properly assign val to each element with the proper operator= of my class. However, when !val, I would like a conversion operator that allows my class to be cast to an int and to produce some values (for example, 0 would make the function above work).
Right now, my program does not compile as it says:
error C2440: 'type cast' : cannot convert from 'const MyClass' to 'int'
How can I create an operator that allows for (int)my_variable with my_variable of type MyClass to be legal, without modifying the function above ?
Something like this using user defined conversions
int type;
explicit operator int()
{
return type;
}
What you want in this case is probably int conversion operator overload:
class A{
public:
explicit operator int() const{
return 2;
}
};
EDIT:
|I added explicit conversion that should make your code compile (at least the method you showed us), and not mess-up other operators, but it's only allowed since C++11, so if you are using older compiler it might not be available yet.

overloading non-member conversion to bool operator

I am trying to write bool-conversion operator for std::bitset
I tried:
template<size_t size>
operator bool(std::bitset<size> & b)
{
return b.any();
}
but I got
error C2801: 'mynamespace::operator bool' must be a non-static member
from my visual-studio.
But when I look up C2801 explanation it says nothing about conversion operators (only about =, ->, [],())
So, is it possible to somehow write "Conversion std::bitset to bool operator?"
(I can not call b.any() in my if-statements, because the same code must run when std::bitset is replaced with unsigned or something
typedef std::bitset<x> Bitset;
//typedef unsigned Bitset;
so the ideal syntax will be like:
Bitset b = whatewer;
if(b)
doStuff();
)
If this overloading is not possible, what is the recommended workaround?
so far I use it like:
if(b == Bitset(0))
doStuff();
but I dont like it.
Thank you
As the error message says, the conversion operator must be a non-static member of a class. That is true.
I can not call b.any() in my if-statements, because the same code must run when std::bitset is replaced with unsigned or something.
If that is your problem, then you can use function overload, and call it passing the argument which will return a boolean value:
template<typename T>
bool to_bool(T const & b)
{
return b; //implicit conversion (if allowed) for all other types
}
template<size_t N>
bool to_bool(std::bitset<N> const & b)
{
return b.any();
}
then use it as:
if (to_bool(whatever))
{
}
It will call the correct overload. If the type of whatever is std::bitset<N> then the second overloaded function will be called, or else the first one will be called.
§12.3.2/1: "A member function of a class X with a name of the form [...] specifies a conversion from X to the type specified..." (C++11 uses the same section number and nearly the same wording, adding only that the function takes no parameters).
The other possible way to define a conversion is a constructor (§12.3.1), which is obviously a class member as well.
In short, yes, conversions must always be defined as member functions.
One way to do what you want would be to write a wrapper around std::bitset that provides the conversion you care about:
template <int size>
class mybitest {
std::bitset<size> bits;
public:
operator bool() { return bits.any(); }
}
But if you decide to do that, you'll need to write forwarding functions for essentially all the pieces of bitset you're using (ctors, assignment, etc.)
The standard is a bit unclear on this (12.3.2):
A member function of a class X having no parameters with a name of the form [...] specifies a conversion from X to the type specified by the conversion-type-id. Such functions are called conversion functions. No return type can be specified. If a conversion function is a member function, the type of the conversion function (8.3.5) is “function taking no parameter returning conversion-type-id”.
The first sentence seems to imply that only member functions can be conversion functions, but I'm not sure what the purpose of the conditional "if a conversion function is a member function" is.
I'd take the first sentence as binding and conclude that a conversion function must be a member function.
in case this helps somebody, you can actually provide a not operator instead
template<size_t size>
operator !(std::bitset<size> & b)
{
return !b.any();
}
and use it like so using the !! idiom:
if (!!whatever)
{
}
still not ideal, but a bit closer I think.

Correct Way to Define a Predicate Function in C++

I'm trying to write predicate function for use with STL algorithms. I see that they are two ways to define a predicate:
(1) Use a simple function as below:
bool isEven(unsigned int i) { return (i % 2 == 0); }
std::find_if(itBegin, itEnd, isEven);
(2) Use the operator() function as below:
class checker {
public:
bool operator()(unsigned int i) { return (i % 2 == 0); }
};
std::find_if(itBegin, itEnd, checker);
I have more use for the second type as I usually would like to create a predicate object with some members in it and use them in the algorithm. When I add the same isEven function inside checker and use it as a predicate, I get an error:
3. Syntax which gives error:
class checker {
public:
bool isEven(unsigned int i)
{ return (i%2 == 0); }
};
checker c;
std::find_if(itBegin, itEnd, c.isEven);
Calling c.isEven gives an error during compilation saying undefined reference to some function. Can someone explain why 3. is giving error? Also, I would appreciate any pointers to read about predicate and iterator basics.
A pointer to a member function requires an instance to be called on, and you are passing only the member function pointer to std::find_if (actually your syntax is incorrect, so it doesn't work at all; the correct syntax is std::find_if(itBegin, itEnd, &checker::isEven) which then still doesn't work for the reasons I gave).
The find_if function expects to be able to call the function using a single parameter (the object to test), but it actually needs two to call a member function: the instance this pointer and the object to compare.
Overloading operator() allows you to pass both the instance and the function object at the same time, because they're now the same thing. With a member function pointer you must pass two pieces of information to a function that expects only one.
There is a way to do this using std::bind (which requires the <functional> header):
checker c;
std::find_if(itBegin, itEnd, std::bind(&checker::isEven, &c, std::placeholders::_1));
If your compiler doesn't support std::bind, you can also use boost::bind for this. Though there's no real advantage to doing this over just overloading operator().
To elaborate a bit more, std::find_if expects a function pointer matching the signature bool (*pred)(unsigned int) or something that behaves that way. It doesn't actually need to be a function pointer, because the type of the predicate is bound by the template. Anything that behaves like a bool (*pred)(unsigned int) is acceptable, which is why functors work: they can be called with a single parameter and return a bool.
As others have pointed out, the type of checker::isEven is bool (checker::*pred)(unsigned int) which doesn't behave like the original function pointer, because it needs an instance of checker to be called on.
A pointer to a member function can be conceptually considered as a regular function pointer that takes an additional argument, the this pointer (e.g. bool (*pred)(checker*, unsigned int)). You can actually generate a wrapper that can be called that way using std::mem_fn(&checker::isEven) (also from <functional>). That still doesn't help you, because now you have a function object that must be called with two parameters rather than only one, which std::find_if still doesn't like.
Using std::bind treats the pointer to a member function as if it was a function taking the this pointer as its first argument. The arguments passed to std::bind specify that the first argument should always be &c, and the second argument should bind to the first argument of the newly returned function object. This function object is a wrapper that can be called with one argument, and can therefore be used with std::find_if.
Although the return type of std::bind is unspecified, you can convert it to a std::function<bool(unsigned int)> (in this particular case) if you need to refer to the bound function object explicitly rather than passing it straight to another function like I did in my example.
I guess it's because the type of c.isEven() is,
bool (checker::*)(unsigned int) // member function of class
which may not be expected by find_if(). std::find_if should be expecting either a function pointer (bool (*)(unsigned int)) or a function object.
Edit: Another constraint: A non-static member function pointer must be called by the class object. In your case, even if you succeed to pass the member function then still find_if() will not have any information about any checker object; so it doesn't make sense to have find_if() overloaded for accepting a member function pointer argument.
Note: In general c.isEven is not the right way to pass member function pointer; it should be passed as, &checker::isEven.
checker::isEven is not a function; it is a member function. And you cannot call a non-static member function without a reference to a checker object. So you can't just use a member function in any old place that you could pass a function pointer. Member pointers have special syntax that requires more than just () to call.
That's why functors use operator(); this makes the object callable without having to use a member function pointer.
I prefer functors (function objects) because make your program more readable and, more importantly, expressing the intent clearly.
This is my favorite example:
template <typename N>
struct multiplies
{
N operator() (const N& x, const N& y) { return x * y; }
};
vector<int> nums{ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
// Example accumulate with transparent operator functor
double result = accumulate(cbegin(nums), cend(nums), 1.1, multiplies<>());
Note: In recent years we've got a lambda expression support.
// Same example with lambda expression
double result = accumulate(cbegin(nums), cend(nums), 1.1,
[](double x, double y) { return x * y; });
The example given says you should use the call operator (operator()) whereas in your example you've called your function isEven. Try re-writing it as:
class checker {
public:
bool operator()(unsigned int i)
{ return (i%2 == 0); }
};