Check Array in MFC C++ - c++

This code that I have is not working as it should.
for (int i = 0; i <= 140; i++)
{
if (OneLine_Array.GetAt(i) == "Pass" || "Fail" || "Warn" || "Active")
{
OneLine_State.Add(OneLine_Array.GetAt(i));
}
}
It will work though if i have it as
for (int i = 0; i <= 140; i++)
{
if ((OneLine_Array.GetAt(i) == "Pass") || (OneLine_Array.GetAt(i) == "Fail") || (OneLine_Array.GetAt(i) == "Warn") || (OneLine_Array.GetAt(i) == "Active"))
{
OneLine_State.Add(OneLine_Array.GetAt(i));
}
}
I was wondering is there a shorter way of doing this rather than replicating the same line of code over and over again?
thanks.

You can store the result of GetAt before you get to the condition, then you don't need to evaluate it multiple times:
auto x = OneLine_Array.GetAt(i);
if (x == "Pass" || x == "Fail" || x == "Warn" || x == "Active")
For a sufficiently short variable name (but please call it something nicer than x), this will be shorter than your second example.
The reason your original condition doesn't work is because each of "Fail", "Warn", and "Active" are true, so the logical OR will also be true. They are true because they are of array type which can be converted to a pointer to their first elements (char*). A non-null pointer is converted to true.

you can't do this ( OneLine_Array.GetAt(i) == "Pass" || "Fail" || "Warn" || "Active") ==> this is not possible in C++
it will be better to save the string of the OneLine_Array.GetAt(i) in variable and make the "=="

Since you mention MFC C++. With a better performance, I'd suggest using CMap (http://msdn.microsoft.com/en-us/library/s897094z.aspx) to store your strings. It does speed up the comparision.

Although I prefer what #sftrabbit answered, you could write a little helper for this.
template<typename A, typename B>
bool equals_one_of(const A& a, const B& b)
{
return a == b;
}
template<typename A, typename B, typename... Args>
bool equals_one_of(const A& a, const B& b, const Args&... args)
{
return equals_one_of(a, b) || equals_one_of(a, args...);
}
int f()
{
if (equals_one_of(OneLine_Array.GetAt(i), "Pass", "Fail", "Warn", "Active"))
{
// ....
}
}

Related

Assign type to a variable and pass it to template

I have the following code
template <typename T>
auto CallMe(int param) -> void {
...
}
auto Test(int userInput) -> void {
int paramToUse = SomeFunction(userInput);
if (userInput == 0) {
CallMe<__int32>(paramToUse);
} else if (userInput == 1) {
CallMe<__int16>(paramToUse);
} else if (userInput == 2) {
CallMe<__int8>(paramToUse);
} else if (userInput == 3) {
...
}
My question is, since all the calls to CallMe() is exactly the same except the template type T, is there a way in C++ to assign the type to a variable in each conditional branch, and pass it to CallMe() in one place, like
typename T;
if (userInput == 0) {
T = __int32;
} else if (userInput == 1) {
T = __int16;
} else if (userInput == 2) {
T = __int8;
} else if (userInput == 3) {
...
CallMe<T>(paramToUse);
This way if the signature of CallMe is changed, only one line is needed to update.
How about:
decltype(CallMe<__int32>)* callable; // function pointer
// set the function address as necessary
if (userInput == 0) {
callable = CallMe<__int32>;
} else if (userInput == 1) {
callable = CallMe<__int16>;
} else if (userInput == 2) {
callable = CallMe<__int8>;
} else {
// ...
}
callable(paramToUse); // call it
Runtime-conditional type aliases aren't possible, as C++ is a statically typed language; meaning all types have to be resolved at compile-time.
Depending on your scenario, you might find a solution using std::variant, however you'll have to pass either pass a new variable to your CallMe function, or replace the type of paramToUse with the variant.
Edit:
using VariantType = std::variant<std::monostate, std::uint8_t, std::uint16_t, std::uint32_t>;
void CallMe(const VariantType value) {
if (const auto uint8Value = std::get_if<std::uint8_t>(&value))
// use uint8Value in a meaningful way
else if (const auto uint16Value = std::get_if<std::uint16_t>(&value))
// ...
// ...
}
void function(const int userInput) {
const auto result = SomeFunction(userInput);
VariantType value {};
if (result == 0)
value = static_cast<std::uint32_t>(123);
else if (result == 1)
value = static_cast<std::uint16_t>(1234);
// more conditions
CallMe(value);
}
since all the calls to CallMe() is exactly the same except the template type T, is there a way in C++ to assign the type to a variable in each conditional branch, and pass it to CallMe() in one place
There isn't, as far I know.
Well... there is using
if (userInput == 0) {
using T = __int32;
} else if (userInput == 1) {
using T = __int16;
} ...
CallMe<T>(paramToUse); // T is out of scope
but the scope of using doesn't extend to the call of the function.
The bad part of your example is that the type is decided from a run-time known value (userInput) so I don't see solution better than the one you're using.
Different if you can pass userInput as compile-time known value: in that case you can create a sort of type array (using std::tuple, for example) and select the type in the call.
For example, suppose userInput is a template parameter value (so known at compile-time) and the userInput value are sequenced starting from zero (as in your question), you can write
template <std::size_t userInput>
void Test ()
{
using typeArray = std::tuple<__int32, __int16, __int8>;
CallMe<std::tuple_element_t<userInput, typeArray>>(paramToUse);
}

Recursive functions with || operator?

So I was tinkering with || and && operators with return. I developed an understanding by comparing int as for example return 1 || 0; return 0 || 0; that the program returns 1 or 0 in case of an int function and true or false in case of bool functions after comparing values.
Now I was writing a code to find path sum to given value using implementation of trees.
bool HasPathSum(ds::sn::BNode<int>* root, int value)
{
if (!root && !value)
{
return true;
}
else if(root)
{
return HasPathSum(root->left, value - root->data)
|| HasPathSum(root->right, value - root->data);
}
return false;
}
I managed to write it after massive tinkering. For recursion I was doing
HasPathSum(root->left, value - root->data);
return HasPathSum(root->right, value - root->data);
To explore all the paths, but it wasn't quite all right because if the path sum was in left, It did go to true but eventually returned false. I figured I will have to write the recursive definition in a single line for it to work and wrote || just as an experiment and it blew my mind that it actually worked. I wrote std::cout << value << " "; at the top of if statement to see what is happening and it does what its supposed do and stops just as a path has been found.
This is all that I've tried but I am unable too wrap my head around how the recursive function with || works or will work if given &&.
If someone experienced can provide an explanation! :)
operator || and operator && does short circuit, so might doesn't evaluate second operand depending of the first one.
bool b = f() || g(); is mostly equivalent to
bool b = f();
if (b == false) b = g();
bool b = f() && g(); is mostly equivalent to
bool b = f();
if (b == true) b = g();

How to properly check multiple times statment

if(a=='b' && b=='b' && c=='b' ...)
Is it the proper way to do this?
I already found other way to solve my problem but would like to know for future times how to do this
If all you have are discrete variables, then you'll have to do this check this way.
There are a few things you'll want to consider though:
It's bad practice to keep using 'b' over and over and over. Either assign it as a constant or have all the other variables compare against the first one, so that if you need to change that 'b' to a 'c' you only have to do it once in the code.
if(a=='b' && a == b && a == c && a == d/*...*/)
Also, this is still a lot of code to maintain. Depending on how long the chain goes (do you go up to a==g && a==h && a == i or further?) You might want to wrap those variables into a vector and iteratively check them.
bool equal = std::find_if_not(
characters.begin(), characters.end(),
[](const char & c) {return c == 'b';}
) == characters.end();
if you'd like a succinct way to describe intent then a little pair of template functions can help you:
template<class X, class Y>
bool all_equal(X&& x, Y&& y)
{
return (x == y);
}
template<class X, class Y, class...Rest>
bool all_equal(X&& x, Y&& y, Rest&&...rest)
{
return all_equal(std::forward<X>(x), std::forward<Y>(y))
&& all_equal(x, std::forward<Rest>(rest)...);
}
which allows code like this:
int main()
{
int a = 10;
int b = 10;
int c = 10;
int d = 11;
std::cout << std::boolalpha << all_equal(a, b) << std::endl;
std::cout << std::boolalpha << all_equal(a, b, c) << std::endl;
std::cout << std::boolalpha << all_equal(a, b, c, d) << std::endl;
}
Your way looks proper. Some coding standards require extra parens like this
if((a=='b') && (b=='b') && (c=='b') ...)
I personally don't think that it is necessary, if you know your operator precedence. see http://www.cppreference.com and search for precedence.

Checking union equality

struct Something {
union {
float k;
int n;
};
bool isFloat;
bool operator==(const Something& mS)
{
if(isFloat != mS.isFloat) return false;
if(isFloat && mS.k == k) return true;
if(!isFloat && mS.n == n) return true;
}
};
My implementation of Something::operator== seems rather expensive and convoluted. Is this the only way to check equality in classes with union types?
Or is there a better way that avoids branches/checking additional variables?
bool operator==(const Something& mS)
{
if (isFloat != mS.isFloat)
{
return false;
}
else if (isFloat)
{
return mS.k == k;
}
else
{
return mS.n == n;
}
}
Clear and debuggable with the minimum number of checks. You want to have a constructor and/or set methods to ensure isFloat is correct at all times.
You can remove one redundant check, and perhaps enhance readability slightly, by replacing the last two lines with
if(isFloat != mS.isFloat) return false; // As you have
return isFloat ? mS.k == k : mS.n == n;
(or the equivalent if construct, as in Sean Perry's answer) but the compiler will probably do just as good a job of optimising your version.
There's no way to avoid a runtime check that the types match. You might consider a ready-made discriminated union type like Boost.Variant; it won't be any more efficient, but it might be easier and less error-prone to use.
return (isFloat && mS.isFloat && k==mS.k) || (!isFloat && !mS.isFloat && n==mS.n);
I do not think that you can escape checking all the conditions. So the question can be how to write them more simpler and expressively.
I would write them the following way
bool operator==( const Something &mS ) const
{
return ( ( isFloat == mS.isFloat ) && ( isFloat ? k == mS.k : n == mS.n ) );
}

C++ "OR" operator

can this be done somehow?
if((a || b) == 0) return 1;
return 0;
so its like...if a OR b equals zero, then...but it is not working for me.
my real code is:
bool Circle2::contains(Line2 l) {
if((p1.distanceFrom(l.p1) || p1.distanceFrom(l.p2)) <= r) {
return 1;
}
return 0;
}
You need to write the full expression:
(a==0)||(b==0)
And in the second code:
if((p1.distanceFrom(l.p1)<= r) || (p1.distanceFrom(l.p2)<=r) )
return 1;
If you do ((a || b) == 0) this means "Is the logical or of a and b equal to 0. And that's not what you want here.
And as a side note: the if (BooleanExpression)return true; else return false pattern can be shortened to return BooleanExpression;
You have to specify the condition separately each time:
if (a == 0) || (b == 0))
bla bla;
When you do
if ((a || b) == 0)
bla bla;
it has a different meaning: (a || b) means "if either a or b is non-zero (ie. true), then the result of this expression is true".
So when you do (a||b) == 0, you are checking if the result of the previously explained expression is equal to zero (or false).
The C++ language specifies that the operands of || ("or") be boolean expressions.
If p1.distanceFrom(l.p1) is not boolean (that is, if distanceFrom returns int, or double, or some numeric class type), the compiler will attempt to convert it to boolean.
For built in numeric type, the conversion is: non-zero converts to true, zero converts to false. If the type of p1.distanceFrom(l.p1) is of class type Foo, the compiler will call one (and only one) user defined conversion, e.g., Foo::operator bool(), to convert the expression's value to bool.
I think you really want something like this:
bool Circle2::contains(Line2 l) {
if((p1.distanceFrom(l.p1) <= r) || (p1.distanceFrom(l.p2) <= r)) return 1;
return 0;
}
Fun with templates:
template <typename T>
struct or_t
{
or_t(const T& a, const T& b) : value1(a), value2(b)
{
}
bool operator==(const T& c)
{
return value1 == c || value2 == c;
}
private:
const T& value1;
const T& value2;
};
template <typename T>
or_t<T> or(const T& a, const T& b)
{
return or_t<T>(a, b);
}
In use:
int main(int argc, char** argv)
{
int a = 7;
int b = 9;
if (or(a, b) == 7)
{
}
return 0;
}
It performs the same comparison you would normally do, though, but at your convenience.
If you have lot of that code, you may consider a helping method:
bool distanceLE (Point p1, Point p2, double threshold) {
return (p1.distanceFrom (p2) <= threshold)
}
bool Circle2::contains (Line2 l) {
return distanceLE (p1, l.p1, r) && distanceLE (p1, l.p2, r);
}
If you sometimes have <, sometimes <=, >, >= and so on, maybe you should pass the operator too, in form of a function.
In some cases your intentions by writing this:
if ((a || b) == 0) return 1;
return 0;
could be expressed with an bitwise-or:
if ((a | b) == 0) return 1;
return 0;
and simplified to
return ! (a | b);
But read up on bitwise operations and test it carefully. I use them rarely and especially I didn't use C++ for some time.
Note, that you inverted the meaning between your examples 1 and 2, returning true and false in the opposite way.
And bitwise less-equal doesn't make any sense, of course. :)
C++ doesn't support any construct like that. Use if (a == 0 || b == 0).
Your condition should be (a == 0 || b == 0) or (p1.distanceFrom(l.p1) <= r || p1.distanceFrom(l.p2)) <= r)
C++ isn't that smart. You have to do each comparison manually.
bool Circle2::contains(Line2 l) {
if((p1.distanceFrom(l.p1) <= r) || (p1.distanceFrom(l.p2) <= r)) return 1;
return 0;
}