Constructor for boolean expression, not the result - c++

I have created a template class called binding_condition so that I can abstract permutations of conditions to a single object. Currently it works with passing a lambda and any variables that need to be checked, but I find the lambda to be misleading since it needs to capture the variables I am referencing.
for example:
bool someVal = true;
int h = 10;
double p = 99.8;
char c = 'C';
binding_condition<bool> bc(
[] (bool b)
{ return b; },
someVal);
binding_condition<bool, int> bc2(
[] (bool b, int i)
{ return b && (i > 9); },
someVal, h);
binding_condition<bool, int, double> bc3(
[] (bool b, int i, double d)
{ return b && (i > 9) && (d < 100); },
someVal, h, p);
binding_condition<bool, int, double, char> bc4(
[] (bool b, int i, double d, char c)
{ return b && (i > 9) && (d < 100) && c == 'C'; },
someVal, h, p, c);
This allows me to abstract some complex condition into a single name:
if (ThisComplexCondition) ...
else if (ThisOtherComplexCondition ...
...
However I am wondering if there is way, either with expression templates or some other method, to allow syntax like this:
binding_condition<bool, int, double> ComplexCondition = myClass.isTrue() && someThing.id < 100 && someDouble > 30.2;
I realize the above expression is not particularly creative, but consider this next one:
// analyzing chords in music to roman numeral notation, detect modulations, etc
// isChordRelatedToKey (the chord can be made from the current key
// isNeopolitan (the chord is a bii6 of the current key
// is major
// letter() is II/ii (ie C# major in C major is not a neapolitan, but Db major is)
// isSecondaryDominant
// chord is major
// chord is dominant of next chord (requires a new temporary key of next chord
// isSecondaryDiminished
// chord is diminished, and is the viio of the next chord
// all other forms of secondary, which means a ii/V in C major is A minor, which is also the vi of the key, and the iii/IV is also A minor
// nested secondary chords ie I - V - V/V - vii/V/V (C major, G major, D major, C# diminished)
// isModulation
// the current string of chords is not related to the current Key anymore
I want to implement some sort of statemachine, package these restrictions into objects, and simply check like:
if (isModulation) ...
if (isSecondary) ... // recursive
if (isChordNoRelation) ... // some chord that makes no sense from previous string
But baby steps at a time. Right now I just want to know if I can assign and store an expression, with whatever variables/functions being referenced in that expression.
Is this possible?

What is wrong with lambda closures, capturing the variables? You don't need to have them passed as parameters. In your first example, you can do this:
bool someVal = true;
int h = 10;
double p = 99.8;
char c = 'C';
auto bc4 = [&](){return someVal && (h > 9) && (p < 100) && c == 'C';};
//later:
if(bc4())
{
/*...*/
}
and for the econd example:
auto ComplexCondition = [&]() { return myClass.isTrue() && someThing.id < 100 && someDouble > 30.2;};
The lambda expressions prodice closures that capture the mentioned variables by reference, so the values are evaluated when the closure operator() is called:
bool someVal = true;
int h = 10;
double p = 99.8;
char c = 'C';
auto bc4 = [&](){return someVal && (h > 9) && (p < 100) && c == 'C';};
if(bc4()) //gives true
{ /* ... */ }
p *= 2;
if (bc4()) {} //gives false, since p > 100

Related

While loop - how to remove code duplication

It's not the first time I find myself in the following situation:
bool a = some_very_long_computation;
bool b = another_very_long_computation;
while (a && b) {
...
a = some_very_long_computation;
b = another_very_long_computation;
}
I don't want to compute everything in while condition, since computations are long and I want to give them appropriate names.
I don't want to create helper functions, because computation uses many local variables, and passing them all will make the code much less readable (and it will be some_huge_call).
It's unknown whether loop body will be executed at least once.
What is a good pattern in such situation? Currently I face it in C++, but I've encountered this in other languages as well. I can solve it by using additional variable isFirstPass, but it looks ugly (and, I guess, will cause some warnings):
bool a, b;
bool isFirstPass = true;
do {
if (!isFirstPass) {
...
} else {
isFirstPass = false;
}
a = some_very_long_computation;
b = another_very_long_computation;
} while (a && b);
The direct simplification of your code is:
while (
some_very_long_computation &&
another_very_long_computation
) {
...
}
If you want to keep the variables a and b:
bool a, b;
while (
(a = some_very_long_computation) &&
(b = another_very_long_computation)
) {
...
}
If you don't want to put the conditions into the while condition:
while (true) {
bool a = some_very_long_computation;
bool b = another_very_long_computation;
if (!(a && b)) {
break;
}
...
}
You could also create helper lambdas (which have access to local variables):
auto fa = [&]() { return some_very_long_computation; };
auto fb = [&]() { return another_very_long_computation; };
while (fa() && fb()) {
...
}

C++ procedure for determining whether two segments intersect

I'm working a bit with computational geometry lately, and I am trying to find a way of checking whether two line segments intersect. I thought that I can use counterclockwise direction (CCW for short) to determine that. Here is my code so far:
struct point { double x, y };
double CCW(point a, point b, point c)
{ return (b.x-a.x)*(c.y-a.y) - (b.y-a.y)*(c.x-a.x); }
int intersect(point a, point b, point c, point d)
{ return (CCW(a,b,c)*CCW(a,b,d)<0 && CCW(c,d,b)*CCW(c,d,a)<0); }
The above code worked for the test cases I entered, and it's pretty readable and very easy to implement. But after searching on the web, I found an other way of solving the segment intersection problem. The code is similar to mine, but it has some more if statements that my implementation omits. Here is the code:
struct line { point s, e; };
int middle(int a, int b, int c) {
int t;
if ( a > b ) {
t = a;
a = b;
b = t;
}
if ( a <= c && c <= b ) return 1;
return 0;
}
int intersect(line a, line b) {
if ( ( CCW(a.s, a.e, b.s) * CCW(a.s, a.e, b.e) < 0 ) &&
( CCW(b.s, b.e, a.s) * CCW(b.s, b.e, a.e) < 0 ) ) return 1;
if ( CCW(a.s, a.e, b.s) == 0 && middle(a.s.x, a.e.x, b.s.x) && middle(a.s.y, a.e.y, b.s.y) ) return 1;
if ( CCW(a.s, a.e, b.e) == 0 && middle(a.s.x, a.e.x, b.e.x) && middle(a.s.y, a.e.y, b.e.y) ) return 1;
if ( CCW(b.s, b.e, a.s) == 0 && middle(b.s.x, b.e.x, a.s.x) && middle(b.s.y, b.e.y, a.s.y) ) return 1;
if ( CCW(b.s, b.e, a.e) == 0 && middle(b.s.x, b.e.x, a.e.x) && middle(b.s.y, b.e.y, a.e.y) ) return 1;
return 0;
}
Could someone explain which is the difference between the two implementations, and which is safer to use? Thanks in advance.
The function that you found is also checking the case where the line segments lie within the same line. In that case, it becomes a one-dimensional problem of finding whether the two line segments overlap. Your code would return false in this case. Whether this is preferred or not depends on the application.
Example:
point a={1,0}, b={3,0}, c={2,0}, d={4,0};
intersect(a,b,c,d); // your function will return false,
// but the one you found will return true
The function you found also looks at cases where the endpoint of one line-segment lies along the other line segment:
Example:
point a={1,0}, b={3,0}, c={2,0}, d={2,3};
intersect(a,b,c,d); // your function will return false,
// but the one you found will return true

how to sort a std::set using more than one key

I need to copy a set to another one based on more than one key.
the keys are used to -collectively- maintain the uniqueness as well as the order of elements in the set.
My class:
class LaneConnector {
public:
const Lane* getLaneFrom() const {
return From;
}
const Lane* getLaneTo() const {
return To;
}
private:
Lane* From;
Lane* To;
}
my functor:
struct MyLaneConectorSorter {
bool operator() (const LaneConnector* rhs, const LaneConnector* lhs) const
{
const Lane* a = lhs->getLaneFrom();
const Lane* b = rhs->getLaneFrom();
bool key1 = a->getLaneID() < b->getLaneID();
bool key2 = a->getLaneParent->ID() < b->getLaneParent->ID();
bool key2 = a->getLaneParent->getParent->ID() < b->getLaneParent->getParent->ID();
//remind you that I NEED the elements to be in ascending order of
//getLaneParent->getParent->ID() ,a->getLaneParent->ID() and then a->getLaneID()
//duplicate elements are the ones which have all three keys same and need to be discarded
return (key1 && key2 && key3); //which dont seem to be working
}
};
and my source and origin sets:
const std::set<LaneConnector*> src = ..... ; //the getter give me a const version
std::set<sim_mob::LaneConnector *, MyLaneConectorSorter> dest;
and how I fill it up:
for(std::set<sim_mob::LaneConnector*>::iterator it = tempLC.begin(); it != tempLC.end(); it++)
{
dest.insert(*it);//I know I can insert it right at the time of declaration, but keep it like this for now...please
}
your kind help would be highly appreciated.
Since getting operator< for multiple tests right is rather hard, I advocate my way of doing this with tuple (in this case with make_tuple instead of tie since we're dealing with temporaries returned from functions):
#include <tuple>
struct MyLaneConectorSorter {
bool operator() (const LaneConnector* lhs, const LaneConnector* rhs) const
{
const Lane* a = lhs->getLaneFrom();
const Lane* b = rhs->getLaneFrom();
auto const* pa = a->getLaneParent();
auto const* pb = b->getLaneParent();
return std::make_tuple(a->getLaneID(), pa->ID(), pa->getParent()->ID()) <
std::make_tuple(b->getLaneID(), pb->ID(), pb->getParent()->ID())
}
This should work and you can get tuple and make_tuple from Boost too, if your compiler doesn't offer them yet.
You need to prioritorise your key field comparisons... only if the most important field is equal, then you compare the second most important - if that's equal then you compare the third most important etc.. As soon as there's an inequality, you return true or false as appropriate. So, it's not a && operation, it should be ? : or an if-else chain, as in:
return lhs.key1 < rhs.key1 ? true :
rhs.key1 < lhs.key1 ? false :
lhs.key2 < rhs.key2 ? true :
rhs.key2 < lhs.key2 ? false :
...
false;
For the set to operate correctly, you must ensure the keys are never equal - so that last false is never actually used.
If you have three member foo, bar and baz to compare on, this is a common way to compare them:
return lhs.foo < rhs.foo
|| lhs.foo == rhs.foo && (lhs.bar < rhs.bar
|| lhs.bar == rhs.bar && lhs.baz < rhs.baz);
Do you see the pattern? ;)
I have problem understanding your sorting rules, but if the relation is a simple sub-sort than the code should look like this:
if (a->getLaneID() < b->getLaneID())
return true;
else if (a->getLaneID() == b->getLaneID())
{
if (a->getLaneParent->ID() < b->getLaneParent->ID())
return true;
// etc...
}
return false;
Your class MyLaneConnectionSorter has a flaw.
std::set expects a comparison class that can order elements. So your comparison function must provide behaviour similar to less functor or operator<, i.e. either a < b or a > b (which is b < a) or a == b (which is !(a < b) && !(a > b))
If we take your comparison function, it will consider Lanes (6, 5, 4) and (7, 3, 4) (in format (PPID, PID, ID)) to be equal, because neither one is less than another. So you need to compare like this:
if (a->getLaneParent->getParent->ID() < b->getLaneParent->getParent->ID()) return true;
else if (a->getLaneParent->getParent->ID() > b->getLaneParent->getParent->ID()) return false;
else {
if (a->getLaneParent->ID() < b->getLaneParent->ID()) return true;
else if (a->getLaneParent->ID() > b->getLaneParent->ID()) return false;
else {
return (a->getLaneID() < b->getLaneID());
}
}

Can C++ do something like an ML case expression?

So, I've run into this sort of thing a few times in C++ where I'd really like to write something like
case (a,b,c,d) of
(true, true, _, _ ) => expr
| (false, true, _, false) => expr
| ...
But in C++, I invariably end up with something like this:
bool c11 = color1.count(e.first)>0;
bool c21 = color2.count(e.first)>0;
bool c12 = color1.count(e.second)>0;
bool c22 = color2.count(e.second)>0;
// no vertex in this edge is colored
// requeue
if( !(c11||c21||c12||c22) )
{
edges.push(e);
}
// endpoints already same color
// failure condition
else if( (c11&&c12)||(c21&&c22) )
{
results.push_back("NOT BICOLORABLE.");
return true;
}
// nothing to do: nodes are already
// colored and different from one another
else if( (c11&&c22)||(c21&&c12) )
{
}
// first is c1, second is not set
else if( c11 && !(c12||c22) )
{
color2.insert( e.second );
}
// first is c2, second is not set
else if( c21 && !(c12||c22) )
{
color1.insert( e.second );
}
// first is not set, second is c1
else if( !(c11||c21) && c12 )
{
color2.insert( e.first );
}
// first is not set, second is c2
else if( !(c11||c21) && c22 )
{
color1.insert( e.first );
}
else
{
std::cout << "Something went wrong.\n";
}
I'm wondering if there's any way to clean all of those if's and else's up, as it seems especially error prone. It would be even better if it were possible to get the compiler complain like SML does when a case expression (or statement in C++) isn't exhaustive. I realize this question is a bit vague. Maybe, in sum, how would one represent an exhaustive truth table with an arbitrary number of variables in C++ succinctly? Thanks in advance.
I like Alan's solution but I respectfully disagree with his conclusion that it is too complex. If you have access to C++11 it gives you almost all the tools you need. You only need to write one class and two functions:
namespace always {
struct always_eq_t {
};
template <class lhs_t>
bool operator==(lhs_t const&, always_eq_t)
{
return true;
}
template <class rhs_t>
bool operator==(always_eq_t, rhs_t const&)
{
return true;
}
} // always
Then you can write your function in a way relatively similar to ML:
#include <tuple>
#include <iostream>
void f(bool a, bool b, bool c, bool d)
{
always::always_eq_t _;
auto abcd = std::make_tuple(a, b, c, d);
if (abcd == std::make_tuple(true, true, _, _)) {
std::cout << "true, true, _, _\n";
} else if (abcd == std::make_tuple(false, true, _, false)) {
std::cout << "false, true, _, false\n";
} else {
std::cout << "else\n";
}
}
int
main()
{
f(true, true, true, true);
f(false, true, true, false);
return 0;
}
In C++ you often want to consider is there a sensible type that I can create that will help me write my code more easily? Additionally, I think if you have a background in ML you will benefit a lot from examining C++ templates. They are very helpful in applying a functional programming style in C++.
C++ is traditionally oriented to the individual, and you could never do anything resembling the following regardless of syntax.
if ([a,b,c,d] == [true,true,false, false]) {}
The New C++ standard has some stuff that lets you define arrays of constants inline, and so it is possible to define a class that will take in an array as a constructor and support such comparisons. Something like
auto x = multi_val({a,b,c,d});
if (x == multi_val({true, true, false, false}))
{ ... }
else if (x == multi_val(etc.))
But now to do partial matches like with the _, that's not directly supported and you'd have to make your class even more complex to fudge with that, like using a maybe template type and going
multi_val(true, true, maybe<bool>(), maybe<bool>)
This gets into rather heady C++ territory and definitely not what I would do for something so elementary.
For C++11 assuming that you only want to match a fixed number of booleans and can live without the _ pattern matching then [1] (Expand to the number of variables you require).
I'm still working on an alternate solution using templates to match arbitrary types using lambdas or functors for the expressions.
-Edit-
As promised, [2] pattern matching of arbitrary types incl. unspecified values.
Note a couple of caveats:
This code only works with 4 variables (actually my first foray into template metaprogramming). This could very much be improved with variadic templates.
It works but it's not very tidy or well organised. More a proof of concept that would need to be cleaned up before introducing into production code.
I'm not happy with the match function. I was hoping to use initializer lists to pass the expressions to be evaluated and stop on the first match (with the current implementation every matching condition will be executed) - however i couldn't quickly think of how to pass expression matching objects of different types via the single initializer list.
I can't think of a method for either to validate that the truth table is exhaustive.
Cheers,
-nick
[1]
constexpr int match(bool v, int c)
{
return v ? (1 << c) : 0;
}
constexpr int match(bool a, bool b)
{
return match(a, 0) | match(b, 1);
}
int main()
{
int a = true;
int b = false;
switch(match(a, b))
{
case match(false, false):
break;
case match(false, true):
break;
case match(true, false):
break;
case match(true, true):
break;
}
}
[2]
template<typename V1, typename V2, typename V3, typename V4>
class pattern_match_t
{
private:
V1 value_0;
V2 value_1;
V3 value_2;
V4 value_3;
public:
typedef std::function<void(V1, V2, V3, V4)> expr_fn;
template <typename C1, typename C2, typename C3, typename C4>
pattern_match_t<V1, V2, V3, V4>& match(C1 a, C2 b, C3 c, C4 d, expr_fn fn)
{
if(value_0 == a && value_1 == b && value_2 == c && value_3 == d)
fn(value_0, value_1, value_2, value_3);
return *this;
}
pattern_match_t(V1 a, V2 b, V3 c, V4 d)
: value_0(a), value_1(b), value_2(c), value_3(d)
{
}
};
template<typename T>
class unspecified
{};
template<typename T>
constexpr bool operator==(unspecified<T>, const T&)
{
return true;
}
template<typename T>
constexpr bool operator==(const T&, unspecified<T>)
{
return true;
}
template<typename V1, typename V2, typename V3, typename V4>
pattern_match_t<V1, V2, V3, V4> pattern_match(V1 a, V2 b, V3 c, V4 d)
{
return pattern_match_t<V1, V2, V3, V4>(a, b, c, d);
}
int main()
{
bool test_a = true;
std::string test_b = "some value";
bool test_c = false;
bool test_d = true;
pattern_match(test_a, test_b, test_c, test_d)
.match(true, unspecified<std::string>(), false, true, [](bool, std::string, bool, bool)
{
return;
})
.match(true, "some value", false, true, [](bool, std::string, bool, bool)
{
return;
});
}

Comparing variables in two instances of a class

i have what i hope is a quick question about some code i am building out.. basically i want to compare the variables amongst two instances of a class (goldfish) to see if one is inside the territory of another. they both have territory clases which in turn use a point clase made up of an x and y data-point.
now i was curious to know why the below doesnt work please:
(this bit of code compares two points: a & b, each with two points, a north-east (ne) and south-west (sw) and their x and y plots)
if ((a->x_ne <= b->x_ne && a->y_ne <= b-> ne) &&
(a->x_sw => b->x_sw && a->y_sw => b-> sw)) {
return true;
} else return false;
I can think of a work around (for instance, by having a get location method), and using a function in the main body to compare, but im curious to know --as a budding c++ programmer -- why the above, or a similar implementation doesnt appear to work.
and also, what would be the CLEANEST and most elegant way to accomplish the above? have a friend function perhaps?
many thanks
edit: added some comments to (hopefully make the variables clearer)
// class point {
// public:
// float x;
// float y;
// point(float x_in, float y_in) { //the 2 arg constructor
// x = x_in;
// y = y_in;
// }
// };
// class territory {
// private:
// point ne, sw;
// public:
// territory(float x_ne, float y_ne, float x_sw, float y_sw)
// : ne(x_ne, y_ne), sw(x_sw,y_sw) {
// }
// bool contain_check(territory a, territory b) {
// //checks if a is contained in b (in THAT order!)
// if ((a->x_ne <= b->x_ne && a->y_ne <= b-> ne) &&
// (a->x_sw => b->x_sw && a->y_sw => b-> sw)) {
// return true;
// } else return false;
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
// };
// class goldfish {
// protected:
// float size;
// point pos;
// territory terr;
// public:
// goldfish(float x, float y) : pos(x,y), terr(x-1,y-1,x+1,y+1) { //constructor
// size = 2.3;
// }
// void retreat() { //what happens in the case of loss in attack
// /*
// if(goldfish.size[1] - goldfish.size[2] <= 1 && goldfish.size[1] - goldfish.size[2] > 0) {
// size = size - 0.2;
// }
// */
// }
// void triumph() {
// }
// void attack() {
// }
// // void goldfish()
// };
On first glance: There isn't a => operator. It's called >=
Assuming that your territories are rectangles and your are detecting overlap by comparing the corners of the two classes (ne and nw) you are only checking the northwest and northeast corners which have a region of a line. As #Éric Malenfant mentioned, you have structures as the class members which are accessed by the '.' operator. Those members are ne and sw so to reference them would be: "a.ne.x"
So starting with this:
if ((a->x_ne <= b->x_ne && a->y_ne <= b-> ne) &&
(a->x_nw => b->x_nw && a->y_nw => b-> nw)) {
return true;
} else return false;
Change it to:
return ( (a.ne.x <= b.ne.x && a.ne.y <= b.ne.y)
&& (a.sw.x >= b.sw.x && a.sw.y >= b.sw.y));
What do you mean by "doesnt work"? I does not compile?
If contain_check is written as shown in your post, a problem is that you are using the arrow operator on non-pointers. Use dot instead:
if ((a.x_ne <= b.x_ne && a.y_ne <= b.ne) //etc.
I noticed two possible problems right off (note: not a C++ expert):
You use => for "greater than or equal to", where it should be >=.
Also, I think b->ne should be b->y_ne.
bool contain_check(territory a, territory b)
You're passing in two territory objects, not pointers to territory objects. Consequently, you'll want to use the . operator to access members instead of the -> operator. Something like:
a.ne
Additionally, you've declared the ne and sw members private, which means that they won't be accessible to unrelated functions. They would need to be public for the contain_check() function to access them.
sorry, i was clearly (very) confused. thanks guys! below works:
if ((a.ne.x <= b.ne.x && a.ne.y <= b.ne.y) &&
(a.sw.x >= b.sw.x && a.sw.y >= b.sw.y)) {
return true;
} else return false;
}
the method bool territory::contain_check(const territory &a, const territory &b); should be declared as static. it makes sense.
or, better, write it as standalone function, because it has nothing to do with the class territory; it checks some kind of relation between two instances, right?