Sending an operator as a paramenter in C++ - c++

I have two variables and an operator (could be any of +, - , /, comparison...).
Is it a good idea to write a function that takes 2 arguments and the operator as the parameters?
Function may be something like below
T foo(int a,int b, sometype(not sure) operator)
and then make a string out of that
foo(a,b,+);
as a+b
Would this be a good approach or is there any other approach?

You can't. Operators are special, they are not ordinary functions. (For instance, operators can have short circuit evaluation and have no overload resolution if all operands are built-in types. Functions cannot do that.)
Pass a binary operation object instead, like:
template <class BinaryOp>
int fun(int, int, BinaryOP);
You can then pass functors like an instance of std::plus<> or binary lambdas† as a third argument. This is a common practice in C++.
Note that functors wrapping the built in operators, such as the aforementioned std::plus, are readily available in the header <functional>.
Sample code for reference:
#include <iostream>
#include <functional>
template <class T>
void fun (int i, int j, T t) {
std::cout << t(i,j) << "\n";
}
int main () {
fun(1,2,std::plus<>{}); // Or std::plus<int>{} in C++11
fun(1,2,[](auto i, auto j){return i * j;}); // Again, with explicit types for C++11
}
This will print
3
2
†As this is tagged C++11: The functors std::plus<T=void> etc. as used in this answer are available in C++14 and later. In C++11, you need to provide a template argument like std::plus<int>. Same goes for the lambda, which would need to become [](int i, int j){...}.

Operators cannot be passed that way, it wouldn't compile: the languages doesn't allow that. You could pass a character that describes the operation to do:
template <class T>
T foo(T lhs, T rhs, char op)
{
switch (op)
{
case '+':
return lhs + rhs;
// other operators
}
}
Another option is passing a function that does the actual computation as parameter:
template <class T, class Operator>
T foo(T lhs, T rhs, Operator op)
{
return op(lhs, rhs);
}
Now you can write your Operators or use the ones already provided: std::plus, std::minus etc. You find them in <functional>.
// ...
foo(5, 10, std::plus<int>{})
If you want to have your versions of these, write the required callables as lambdas or functions:
template <class T>
T add(T lhs, T rhs) { return lhs + rhs; }
foo(5, 10, add<int>);
foo(5, 10, [](int a, int b){ return a + b; }); // or use `auto` to make it generic

Related

How to get a function pointer to a built-in arithmetic operator? [duplicate]

I want to refer to function pointers of built-in operators, but I don't know how to specify the specific type overloads.
I have the following template class signature:
template<typename ParamsType, typename FnCompareType>
class MyAction
{
public:
MyAction(ParamsType& arg0, ParamsType& arg1, FnCompareType& fnCpmpare)
: arg0_(arg0), arg1_(arg1), fnCompare_(fnCpmpare) {}
bool operator()()
{
if((*fnCompare_)(arg0_,arg1_)
{
// do this
}
else
{
// do s.th. else
}
}
private:
ParamsType& arg0_;
ParamsType& arg1_;
FnCompareType& fnCompare_;
}
And want to use a syntax like this:
void doConditional(int param1, int param2)
{
MyAction<int,&::operator>=> action(param1,param2);
if(action())
{
// Do this
}
else
{
// Do that
}
}
But that doesn't compile:
error: ‘::operator>=’ has not been declared
What can I do to refer to such intrinsic static operations?
Built-in operators
Why you cannot have function pointers of them:
C++11, §13.6/1, [over.built]
The candidate operator functions that represent the built-in operators defined in Clause 5 are specified in this subclause. These candidate functions participate in the operator overload resolution process as described in 13.3.1.2 and are used for no other purpose.
Built-in operators (those for the built-in types) aren't real operator functions. So you can't have function pointer pointing to them. You also cannot invoke them using operator<(A,B) syntax.
They only participate in overload resolution but the compiler will translate them directly into the appropriate asm/machine instruction without any kind of "function call".
The way to get around this issue:
user1034749 has already answered this question, but for completeness:
The standard defines a lot of function objects in §20.8, [function.objects], i.e.
Arithmetic operations
Comparisons
Logic operations
Bitwise operations
A function object is an object of a function object type. In the places where one would expect to pass a pointer to a function to an algorithmic template (Clause 25), the interface is specified to accept a function object. This not only makes algorithmic templates work with pointers to functions, but also enables them to work with arbitrary function objects.
C++11, §20.8.5, [comparisons]
equal_to
not_equal_to
greater, less
greater_equal
less_equal
Those are templated function objects which decay to the analogous operator in their operator() function. They can be used as function pointer arguments.
user1034749 is right, I want to state: There's no other way, these are completely equivalent in usage to 'raw' function pointers. Reference given.
Standard class type operators
You can use standard library operators as function pointers (which are present as "real functions").
But you'll have to refer to the respective instance of the template. The compiler will need appropriate hints to deduce the correct template.
This works for me on MSVC 2012 using operator+ of std::basic_string
template<class Test>
Test test_function (Test const &a, Test const &b, Test (*FPtr)(Test const &, Test const &))
{
return FPtr(a, b);
}
int main(int argc, char* argv[])
{
typedef std::char_traits<char> traits_t;
typedef std::allocator<char> alloc_t;
std::basic_string<char, traits_t, alloc_t> a("test"), b("test2");
std::cout << test_function<std::basic_string<char, traits_t, alloc_t>>(a, b, &std::operator+) << std::endl;
return 0;
}
If the template argument of test_function is left out to be deduced this will fail (at least for MSVC 2012).
You can use the same solution as used in C++ standard library:
std::sort (numbers, numbers+5, std::greater<int>());
where greater is
template <class T> struct greater : binary_function <T,T,bool> {
bool operator() (const T& x, const T& y) const {return x>y;}
};
in your case http://www.cplusplus.com/reference/functional/greater_equal/
About reference of built operator.
You can reference existing operator< for any class (of course if they are not private, protected or your class/function not friend).
But opeator< for builtin types (bool, short, int, double) it is not possible reference.
Event if not look at C++ standard you can see from my text above.
An extension to the solution provided by fghj, that would work for assignment type operators, such as +=/-=, etc would be to wrap these similarly to the standard variants. You could then do:
#include <iostream>
template <typename T>
struct assign_plus {
void operator() const (T& a, const T& b){
a += b;
}
};
template <typename T>
struct assign_minus {
void operator() const (T& a, const T& b){
a -= b;
}
};
template<template <class T> class O> requires requires(int& a, const int& b){
{ O<int>{}(a,b) };
}
void example(int& a, const int& b){
O<int>{}(a,b);
}
int main(){
int a = 5;
int b = 6;
example<assign_plus>(a,b);
std::cout << a << "\n";
example<assign_minus>(a,b);
std::cout << a << "\n";
return 0;
}
where the constraint could be kept/removed given c++20 compatibility. These constraints then also could be extended to require that a += b is valid (for custom types for example).

function pointers using '<' as an operator [duplicate]

I want to refer to function pointers of built-in operators, but I don't know how to specify the specific type overloads.
I have the following template class signature:
template<typename ParamsType, typename FnCompareType>
class MyAction
{
public:
MyAction(ParamsType& arg0, ParamsType& arg1, FnCompareType& fnCpmpare)
: arg0_(arg0), arg1_(arg1), fnCompare_(fnCpmpare) {}
bool operator()()
{
if((*fnCompare_)(arg0_,arg1_)
{
// do this
}
else
{
// do s.th. else
}
}
private:
ParamsType& arg0_;
ParamsType& arg1_;
FnCompareType& fnCompare_;
}
And want to use a syntax like this:
void doConditional(int param1, int param2)
{
MyAction<int,&::operator>=> action(param1,param2);
if(action())
{
// Do this
}
else
{
// Do that
}
}
But that doesn't compile:
error: ‘::operator>=’ has not been declared
What can I do to refer to such intrinsic static operations?
Built-in operators
Why you cannot have function pointers of them:
C++11, §13.6/1, [over.built]
The candidate operator functions that represent the built-in operators defined in Clause 5 are specified in this subclause. These candidate functions participate in the operator overload resolution process as described in 13.3.1.2 and are used for no other purpose.
Built-in operators (those for the built-in types) aren't real operator functions. So you can't have function pointer pointing to them. You also cannot invoke them using operator<(A,B) syntax.
They only participate in overload resolution but the compiler will translate them directly into the appropriate asm/machine instruction without any kind of "function call".
The way to get around this issue:
user1034749 has already answered this question, but for completeness:
The standard defines a lot of function objects in §20.8, [function.objects], i.e.
Arithmetic operations
Comparisons
Logic operations
Bitwise operations
A function object is an object of a function object type. In the places where one would expect to pass a pointer to a function to an algorithmic template (Clause 25), the interface is specified to accept a function object. This not only makes algorithmic templates work with pointers to functions, but also enables them to work with arbitrary function objects.
C++11, §20.8.5, [comparisons]
equal_to
not_equal_to
greater, less
greater_equal
less_equal
Those are templated function objects which decay to the analogous operator in their operator() function. They can be used as function pointer arguments.
user1034749 is right, I want to state: There's no other way, these are completely equivalent in usage to 'raw' function pointers. Reference given.
Standard class type operators
You can use standard library operators as function pointers (which are present as "real functions").
But you'll have to refer to the respective instance of the template. The compiler will need appropriate hints to deduce the correct template.
This works for me on MSVC 2012 using operator+ of std::basic_string
template<class Test>
Test test_function (Test const &a, Test const &b, Test (*FPtr)(Test const &, Test const &))
{
return FPtr(a, b);
}
int main(int argc, char* argv[])
{
typedef std::char_traits<char> traits_t;
typedef std::allocator<char> alloc_t;
std::basic_string<char, traits_t, alloc_t> a("test"), b("test2");
std::cout << test_function<std::basic_string<char, traits_t, alloc_t>>(a, b, &std::operator+) << std::endl;
return 0;
}
If the template argument of test_function is left out to be deduced this will fail (at least for MSVC 2012).
You can use the same solution as used in C++ standard library:
std::sort (numbers, numbers+5, std::greater<int>());
where greater is
template <class T> struct greater : binary_function <T,T,bool> {
bool operator() (const T& x, const T& y) const {return x>y;}
};
in your case http://www.cplusplus.com/reference/functional/greater_equal/
About reference of built operator.
You can reference existing operator< for any class (of course if they are not private, protected or your class/function not friend).
But opeator< for builtin types (bool, short, int, double) it is not possible reference.
Event if not look at C++ standard you can see from my text above.
An extension to the solution provided by fghj, that would work for assignment type operators, such as +=/-=, etc would be to wrap these similarly to the standard variants. You could then do:
#include <iostream>
template <typename T>
struct assign_plus {
void operator() const (T& a, const T& b){
a += b;
}
};
template <typename T>
struct assign_minus {
void operator() const (T& a, const T& b){
a -= b;
}
};
template<template <class T> class O> requires requires(int& a, const int& b){
{ O<int>{}(a,b) };
}
void example(int& a, const int& b){
O<int>{}(a,b);
}
int main(){
int a = 5;
int b = 6;
example<assign_plus>(a,b);
std::cout << a << "\n";
example<assign_minus>(a,b);
std::cout << a << "\n";
return 0;
}
where the constraint could be kept/removed given c++20 compatibility. These constraints then also could be extended to require that a += b is valid (for custom types for example).

Binding of regular function to std::function

I am trying to code a functional composition using operator overloading in C++, so to have a simple composition syntax similar to the ones in functional languages (e.g. Haskell). My aim is to use regular bare C++ functions in the composition. There are two overloads which I coded so far:
operator% which uses two function<int(int)> parameters and
operator* which uses template type as parameters.
operator% works well, but in main() I have firstly to wrap regular functions into function<int(int)> in order operator% to accept them as input parameters. I want to avoid this additional step by migrating it into overloaded operator* which uses template parameters. I thought that it is possible to bind regular functions to the template parameters of operator*, but compiler reports the error:
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;
Do you have any idea how to solve this issue? Using template parameters in operator*is not mandatory - if you have some other approach simply suggest here.
Here is the source code:
#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
}
EDIT: Solution given by Zac uses a class type for one of function arguments (it is mandatory, by the standard, to use at least one enum or class type argument in operator overloads) and a template type argument. Then regular C++ functions gladly bind to both arguments. Thus the final operator overload is quite simple:
template<typename T>
function<int(int)> operator*(function<int(int)> f, T g)
{
return [=](int x){ return f(g(x));};
}
and regular functions can be composed then using simple (f*g)(x) syntax.
The only idea that comes to mind is to start with some dummy:
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
}
As Daniel pointed out, one of the argument in the operator overload has to be class or enumerated type. Therefore the call to f*g needs to be instantiated to function<int(int)> instead of function pointer type. There are two options for this problem,
use function instead of operator, such as
template<typename T>
function<int(int)> multi(T x, T y)
declare one of the function parameter as `function
template<typename T>
function<int(int)> operator*(function<int(int)> x, T y)

Generic equivalent to std function objects

Is there any function objects in the boost that are generic equivalents to the std::equal_to, std::greater etc. family of function objects?
Essentially, std::equal_to should become something like
struct generic_equal_to
{
template <class T, class U>
bool operator()(const T& t, const U& u) const
{
return t == u;
}
};
I can see how the generic versions of std::plus etc. might be trickier due to issues with the return type (though the decltype can solve that). I can't see any possible reason why the std::equal_to function object itself should require a template argument, though.
Surely somewhere in boost or in the STL these versions exist? They are, of course, trivial to write, but I very much dislike duplicating library code, especially for something as apparently trivial as this.
EDIT:
As some context as to why I would want this instead of using lambdas, or another function-object generation method:
I was writing a generic boost::fusion sequence comparison function thusly:
template <class T>
bool sequence_equal(const T& left, const T& right)
{
return fusion::all(
fusion::zip(left, right),
fusion::fused<generic_equal_to>());
}
Note the fusion::fused<generic_equal_to> part, which leads to the isse that you can't practically specify a boost::lambda or boost::phoenix function-object by type. I guess one solution might be decltype:
fusion::fused<decltype(_1 == _2)>()
That seems very awkward though, and might not even work, depending on how boost::lambda or boost::phoenix is implemented - I'm really not sure.
I know you can use fusion::make_fused to get around this whole issue, but then you have to instantiate the function object. The solution I thought of, then, would be a non-template equal_to struct - I called mine generic_equal_to.
I know it's a very trivial problem - after all, make_fused(_1 == _2) will probably inline down to much the same assembly as fused<generic_equal_to>. I just couldn't believe that there was no generic_equal_to function object in boost or in the STL anywhere, hence this question.
I don't think there's anything quite as direct as you're asking for, but there are utilities that not only cover your use-cases, but go beyond. They are Boost.Lambda and Boost.Phoenix (the latter being a more generic successor to the lambda library).
Example using Boost.Lambda for generic equality:
#include <boost/lambda/lambda.hpp>
#include <iomanip>
#include <iostream>
struct foo {};
bool operator==(foo, foo) { return true; }
bool operator==(foo, int) { return false; }
template <typename T, typename U, typename Func>
void f(const T& x, const U& y, Func func)
{
std::cout << func(x, y) << std::endl;
}
int main()
{
using namespace boost::lambda; // for placeholders
std::cout << std::boolalpha;
foo a, b;
int i = 0;
f(a, b, _1 == _2);
f(a, i, _1 == _2);
}
And the same, with Phoenix:
#include <boost/phoenix.hpp>
#include <iomanip>
#include <iostream>
struct foo {};
bool operator==(foo, foo) { return true; }
bool operator==(foo, int) { return false; }
template <typename T, typename U, typename Func>
void f(const T& x, const U& y, Func func)
{
std::cout << func(x, y) << std::endl;
}
int main()
{
using namespace boost::phoenix::arg_names; // for placeholders
std::cout << std::boolalpha;
foo a, b;
int i = 0;
f(a, b, arg1 == arg2);
f(a, i, arg1 == arg2);
}
Each of these can be extended to support the other operators in the obvious way (and more generally, into other expressions). I would personally go with Phoenix, because if you find out you need more functionality than lambda offers you won't end up including both.
Now in C++14 there is std::equal_to<void> (that can be also used as std::equal_to<>)
std::equal_to<> is a specialization of std::equal_to with parameter and return type deduced.
template< class T, class U>
constexpr auto operator()( T&& lhs, U&& rhs ) const
-> decltype(std::forward<T>(lhs) == std::forward<U>(rhs));
Returns the result of equality comparison between lhs and rhs.
Docs

Syntactic sugar: automatically creating simple function objects

I am to implement a set of class templates and two special variables, _1 and _2.
They should make the following a legal code:
// Sort ascending
std::sort(a, a+5, _1 > _2);
// Output to a stream
std::for_each(a, a+5, std::cout << _1 << " ");
// Assign 100 to each element
std::for_each(a, a+5, _1 = 100);
// Print elements increased by five 5
std::transform(a, a+5, std::ostream_iterator<int>(std::cout, " "), _1 + 5);
I suppose that _1 * 5 should also yield an unary function, as well as _1 / 5 etc.
No boost allowed
No lambdas allowed
Now I have very little experience with templates and template metaprogramming, so I don't even know where to start and what the structure of my class templates should look like. I am especially confused as I don't know if inside my class templates I will have to write implementations for all these operator=, operator>>, operator+, ...-, ...*, .../ separately - or there is a more generic way to do it.
I will be particularly grateful to an answer with an example of implementation of these operators; templates still seem like a great mess to me.
Well! That is a tricky homework problem, indeed! But, it's also a very good problem to work on and to learn from.
I think that the best way to answer this is for you to start off with simple use cases and incrementally build up your solution.
For example, suppose that you have the following std::vector<int> to work with:
std::vector<int> vec;
vec.push_back(4);
vec.push_back(-8);
vec.push_back(1);
vec.push_back(0);
vec.push_back(7);
You'll obviously want to allow the following use case:
std::for_each(vec.cbegin(), vec.cend(), _1);
But how to allow this? First you'll need to define _1 and then you'll need to implement an "anything goes" overload of the function call operator for the type of _1.
The way that Boost Lambda and Boost Bind define placeholders objects _1, _2, ... is to make them have a dummy type. For example, the _1 object might have the type placeholder1_t:
struct placeholder1_t { };
placeholder1_t _1;
struct placeholder2_t { };
placeholder2_t _2;
Such a "dummy type" is frequently, informally called a tag type. There are many C++ libraries and indeed the STL that rely on tag types (e.g. std::nothrow_t). They are used to pick the "right" function overload to execute. Essentially, dummy objects are created having a tag type and these are passed into a function. The function does not use the dummy object in any way (in fact, most of the time a parameter name is not even specified for it), but by the existence of that extra parameter, the compiler is able to pick the correct overload to call.
Let's extend the definition of placeholder1_t by adding overloads of the function call operator. Remember that we want it to accept anything, so the overloads of the function call operator will themselves be templated on the argument type:
struct placeholder1_t
{
template <typename ArgT>
ArgT& operator()(ArgT& arg) const {
return arg;
}
template <typename ArgT>
const ArgT& operator()(const ArgT& arg) const {
return arg;
}
};
That's it! Our simplest of use cases will now compile and run:
std::for_each(vec.cbegin(), vec.cend(), _1);
Of course, it basically amounts to a no-op.
Let's now work on _1 + 5. What should that expression do? It should return a unary functional object that, when invoked with an argument (of some unknown type), the result is that argument plus 5. Making this more generic, the expression is unary-functional-object + object. The returned object is itself a unary functional object.
The type of the returned object needs to be defined. It will be a template with two template type parameters: the unary functional type and the type of the object that is being added to the result of the unary functional:
template <typename UnaryFnT, typename ObjT>
struct unary_plus_object_partfn_t;
"partfn" refers to a functional type representing partial application of the binary + operator. Instances of this type need a copy of the unary functional object (having type UnaryFnT) and the other object (having type ObjT):
template <typename UnaryFnT, typename ObjT>
struct unary_plus_object_partfn_t
{
UnaryFnT m_fn;
ObjT m_obj;
unary_plus_object_partfn_t(UnaryFnT fn, ObjT obj)
: m_fn(fn), m_obj(obj)
{
}
};
Okay. The function call operator also needs to be overloaded to allow for any argument. We'll use the C++11 decltype feature to refer to the type of an expression as we don't know what it is beforehand:
template <typename UnaryFnT, typename ObjT>
struct unary_plus_object_partfn_t
{
UnaryFnT m_fn;
ObjT m_obj;
unary_plus_object_partfn_t(UnaryFnT fn, ObjT obj)
: m_fn(fn), m_obj(obj)
{
}
template <typename ArgT>
auto operator()(ArgT& arg) const -> decltype(m_fn(arg) + m_obj) {
return m_fn(arg) + m_obj;
}
template <typename ArgT>
auto operator()(const ArgT& arg) const -> decltype(m_fn(arg) + m_obj) {
return m_fn(arg) + m_obj;
}
};
It's starting to get complicated, but there are no surprises in this code. It essentially says that the function call operator is overloaded to accept practically any argument. It will then call m_fn (the unary functional object) on the argument and add m_obj to the result. The return type is the decltype of m_fn(arg) + m_obj.
Now that the type is defined, we can write the overload of binary operator + accepting an object of type placeholder1_t on the left:
template <typename ObjT>
inline unary_plus_object_partfn_t<placeholder1_t, ObjT> operator+(const placeholder1_t& fn, ObjT obj)
{
return unary_plus_object_partfn_t<placeholder1_t, ObjT>(fn, obj);
}
We now can compile and run the second use case:
std::transform(vec.cbegin(), vec.cend(), std::ostream_iterator<int>(std::cout, " "), _1 + 5);
std::cout << std::endl;
which outputs:
9 -3 6 5 12
This is basically all that you need to do to solve the problem. Think about how you can write custom functional types, instances of which can be returned by overloads of operators.
EDIT: Improved the overloads of function call operators by employing pass-by-reference.
EDIT2: In some cases it will be necessary to store a reference to an object rather than a copy of it. For example, to accommodate std::cout << _1, you will need to store a reference to std::cout in the resulting functional object because the std::ios_base copy constructor is private, and it is impossible to copy construct objects of any class derived from std::ios_base including std::ostream.
To allow for std::cout << _1, you might want to write a ref_insert_unary_partfn_t template. Such a template, like the example of unary_plus_object_partfn_t above, would be templated on an object type and a unary functional type:
template <typename ObjT, typename UnaryFnT>
struct ref_insert_unary_partfn_t;
Instances of instantiations of this template will need to store a reference to an object of type ObjT as well as a copy of a unary functional object of type UnaryFnT:
template <typename ObjT, typename UnaryFnT>
struct ref_insert_unary_partfn_t
{
ObjT& m_ref;
UnaryFnT m_fn;
ref_insert_unary_partfn_t(ObjT& ref, UnaryFnT fn)
: m_ref(ref), m_fn(fn)
{
}
};
Add overloads of the function call operator as before as well as overloads of the insertion operator, <<.
In the case of std::cout << _1, the returned object would have the type ref_insert_unary_partfn_t<std::basic_ostream<char>, placeholder1_t>.
A simple example:
template <typename T>
class Parameter
{
};
template <typename T>
struct Ascending
{
bool operator()(T left, T right)
{
return left < right;
}
};
template <typename T>
Ascending<T> operator > (Parameter<T> p1, Parameter<T> p2)
{
return Ascending<T>();
}
int main()
{
std::vector<int> vec;
vec.push_back(3);
vec.push_back(6);
vec.push_back(7);
vec.push_back(2);
vec.push_back(7);
std::vector<int>::iterator a = vec.begin();
Parameter<int> _1;
Parameter<int> _2;
std::sort(a, a+4, _1 > _2);
}