Passing operator as a parameter
Solution 1
Declare:
template<class Func> bool myfunc(char lv, char rv, Func func);
Or if you need to link it separately:
bool myfunc(char lv, char rv, std::function<bool(bool,bool)> func);
Then you can call:
myfunc('t', 'f', std::logical_or<bool>());
Solution 2
@ybungalobill posted a C++ correct answer and you should stick to it. If you want to pass the operators, functions will not work, but macros would do the work:
#define MYFUNC(lv, rv, op) ....
// Call it like this
MYFUNC('t', 'f', ||);
Be careful, macros are evil.
Solution 3
What you can do is define proxy operators that return specific types.
namespace detail {
class or {
bool operator()(bool a, bool b) {
return a || b;
}
};
class and {
bool operator()(bool a, bool b) {
return a && b;
}
};
// etc
class X {
or operator||(X x) const { return or(); }
and operator&&(X x) const { return and(); }
};
};
const detail::X boolean;
template<typename T> bool myfunc(bool a, bool b, T t) {
return t(a, b);
}
// and/or
bool myfunc(bool a, bool b, std::function<bool (bool, bool)> func) {
return func(a, b);
}
// example
bool result = myfunc(a, b, boolean || boolean);
You can if desperate chain this effect using templates to pass complex logical expressions.
Also, the XOR operator is bitwise, not logical- although the difference is realistically nothing.
However, there's a reason that lambdas exist in C++0x and it's because this kind of thing flat out sucks in C++03.
Solution 4
In modern C++ can pass any operator by using lambdas.
Update 1: the proposed solution introduces small improvement which is suggested by @HolyBlackCat
#include <iostream>
template<class T, class F> void reveal_or(T a, T b, F f)
{
// using as function(a, b) instead of expression a || b is the same thing
if ( f(a, b) )
std::cout << a << " is || " << b << std::endl;
else
std::cout << a << " is not || " << b << std::endl;
}
template<class T> void reveal_or(T a, T b)
{
// reuse the already defined ||
reveal_or(a, b, [](T t1, T t2) {return t1 || t2; });
}
Don't bother how to pass parameter if || operator is defined
int main ()
{
reveal_or('1', 'a');
return 0;
}
Passing explicitly as parameter. We can pass anything, including including any exotic nonsense
int main ()
{
//same as above:
reveal_or('1', 'a', [](char t1, char t2) { return t1 || t2; });
//opposite of above
reveal_or('1', 'a', [](char t1, char t2) { return !( t1 || t2; ) });
return 0;
}
nacho4d
C/C++/Objective-C/C#/Javascript/shell-script/Japanese/Go/Spanish/English I love this site. So Helpful! https://twitter.com/nacho4d http://nacho4d-nacho4d.blogspot.com/
Updated on September 27, 2021Comments
-
nacho4d over 2 years
I want to have a function that evaluates 2
bool
vars (like a truth table).For example:
Since
T | F : T
then
myfunc('t', 'f', ||); /*defined as: bool myfunc(char lv, char rv, ????)*/
should
return true;
.How can I pass the third parameter?
(I know is possible to pass it as a char* but then I will have to have another table to compare operator string and then do the operation which is something I would like to avoid)
Is it possible to pass an operator like
^
(XOR) or||
(OR) or&&
(AND), etc to a function/method? -
Billy ONeal over 13 yearsCorrect me if I'm wrong, but isn't overloading
operator||
andoperator&&
evil? -
Billy ONeal over 13 yearsThis isn't true. STL functors are typically not function pointers.
-
Puppy over 13 years@Billy: No- why would it be? This is no different to the _1 and etc in boost::bind.
-
Billy ONeal over 13 yearsSorry... didn't see that those were inside classes :P Thought you were breaking short circuit semantics for every expression containing
&&
or||
! -
ltjax over 13 yearsOverloading
operator||
andoperator&&
is evil (because such overloads are no longer lazy and evaluate their params in undefined order) unless they are used for expression templates (where that does not matter) like in this case. -
erinus over 13 yearsI think that STL functors is also an object, so it also has a memory address to send into function parameter.
-
Konrad Rudolph over 13 yearsthat’s irrelevant. You can overload operators and pass them to functions. It just so happens that this cannot be done (for no good reasons) with pre-defined operators of built-in types. So passing operators to functions definitely works – just not in this very particular case (unless you use the trick shown by DeadMG, then it even works for this case).
-
erinus over 13 yearsThanks for Konrad. I don't know this. And I wanna know that: overload operator -> create class's RTTI extra info for the operator, so for compiler, it's not a default operator(compiler make it with default binary code). overload parameter will compile to reference RTTI to know how operator handle its action. so it can pass the reference, and default operator can't pass. Is it right?(I'm not good at English. Sorry.)
-
Brett Rossier almost 13 yearsJust thought it'd be helpful to include a link to more function objects like std::logical_or cplusplus.com/reference/std/functional
-
Patrick over 4 years@ybungalobill I tried to implement
myfunc
asreturn func(int(lv), rv(lv))
. But calling it likemyfunc('1', '3', std::plus<int>());
then returns just1
instead of4
. Isn't that meant to be used like that? -
Yakov Galka over 4 years@Patrick:
myfunc
returnsbool
, so it cannot return4
. Also'1' == 49
and'3' == 51
, so the answer I would expect is100 == 'd'
. -
HolyBlackCat about 3 yearsHaving
std::function
as a default argument saves typing, but gives you extra overhead compared to a plain lambda. I'd write two overloads, one with 3 params and no default args, and the other with two parameters, calling the first one.