operator precedence (void* before bool?) - c++

When answering this question I made some research which really confuses me.
I noticed that two ifstreams that succesfully open are not equal but two ifstreams that fail are.
At first i checked cplusplus.com. The operator ! returns the status of the badbit and failbit. I think that the opposite of this would still be to return the status of these two bits, but flipped.
Wrong, because two succesful calls are not equal.
So then I figured it was an operator bool somewhere that would return something. So I tried to backtrack from ifstream and found the istream::operator bool(), which is returning _Ok.
Still wrong however, this doesn't seem to be called at all (and couldn't be, since the two successful calls are still not equal).
So I changed my approach and checked the disassembly from Visual Studio. And what do I find?
if (file0 != file1) { doesn't call the operator bool(), but rather the operator void* () (or really __imp_std::ios_base::operator void *).
So the questions I have are..
Shouldn't any operator bool () found be called before trying to casting it to pointer values?
Is it some operator bool() I missed that in turn is calling the operator void* ?
Is this some optimizing that I don't understand?
Or am I completely wrong in that C++ actually thinks that void* is a better match than bool in this comparison?

1.) You cannot overload multiple times but with different return types.
2.) Yes, operator! returns the badbit/failbit, but operator! is something entirely different from operator!=, which is the one you are using.

Related

Different behavior ternary operator - if/else with spread operator (...)

Why the following code works fine with if/else and not with ternary operator?
ListView(
children: [
// Commented code not working
// isLogged ? ...loggedRows(context) : loginRow(context),
// Working code
if (isLogged)
...loggedRows(context)
else
loginRow(context),
ListTile(...),
ListTile(...),
])
loggedRows and loginRow methods:
ListTile loginRow(BuildContext context) {
return ListTile(...)
}
List<ListTile> loggedRows(BuildContext context) {
return [ListTile(...), ListTile(...)];
}
I try to show different ListTiles depending on if the user is logged in or not, and it works perfectly using if/else but when I try to do the same with ternary operator I get error.
I tried several parenthesis combinations, but none of them worked for me.
Using the simplest mode, as in commented code, I get 3 errors on Dart Analysis:
Expected to find ']'.
Expected to find '.'.
Expected an identifier.
Shouldn't behave the same ternary operator and if/else?
Why do I get these errors?
Does anyone know which should be the right syntax to use ternary operator?
Your use of the ternary operator doesn't work because each of the "then" and "else" operands (and therefore the result of the ternary operator itself) must evaluate to an expression, and the spread operator (...) doesn't produce an expression. The spread operator (and collection-if and collection-for) instead evaluates to one or more collection elements. (I highly recommend reading Bob Nystrom's article that discusses the design of these language features.)
Your use of the ternary operator would work if you moved the spread operator out:
...(isLogged ? loggedRows(context) : [loginRow(context)]),
although that is more awkward since it creates an extra List if isLogged is false. Using collection-if instead would be much more appropriate for this usage.

How to fully bypass `error: no match for ‘operator==’`?

I am using a program called SlideSort, which does not compile anymore on a recent Debian system using GCC 6.3.0. Instead, it throws the following error:
mstree.cpp:228:11: error: no match for ‘operator==’ (operand types are ‘std::ofstream {aka std::basic_ofstream<char>}’ and ‘long int’)
if(dFile==NULL){
^
Not being a C programmer, I tried to bypass the problem by gently telling the compiler that the code is old; in my understanding this is roughly what GCC's option -std=c++98 does. (See in GitHub's issue tracker for the patch to the Makefile).
Then the code compiles. but it segfaults in some corner cases (Test data and command available in GitHub's issue tracker). The same test command works fine when the program is compiled with GCC 4.9.4.
Thus, passing -std=c++98 to GCC was either not enough or a wrong idea altogether. Is there an alternative to either compile on an old system or updated the code to the latest standards (which I can not do by myself) ?
I do not know why this code ever worked. In no version of the C++ standard is a scalar stream object comparable to an integer or to nullptr_t. That being said, your question is not how to fix the code you've found but how to bypass the error. I do not recommend doing what I'm about to say here in production code. It's a hack, and it's only designed to get an unusual library like this working.
The == operator can be defined outside of any class, as a standalone function. The library you're using compares std::ofstream to long int. Let's make that comparison valid.
bool operator==(const std::ofstream&, long int) {
return false;
}
Now your code will compile. But it will probably run incorrectly. You could try making the comparison smarter by having it check whether the std::ofstream is truthy.
bool operator==(const std::ofstream& out, long int n) {
return (bool)out == (bool)n;
}
Now it's a bit smarter. But there's no silver bullet here. The code you were given is not working and not standard C++, so there's no fullproof way to get it working without changing the actual library code. So my suggestion is to fork the repository and fix the broken line of code yourself.
In C++ 98 the streams used to have an operator void*() to check the stream state. It returned a null pointer when the stream was in an error state. Turned out that this implicit conversion caused some unexpected results when accidentally invoked in odd places.
So in C++11, which gained explicit operators, it was turned into an explicit operator bool() instead. This returns true for a good state and false when the stream is in a failed state.
Being explicit it can also only be used in places where a bool is expected. This removes most of the unexpected conversions from the old operator.
So if(dFile==NULL), testing for a non-good state of the stream, is now written if (!dFile).
And actually, the tests if (dfile) (good state) and if (!dFile) (non-good state) have always worked. The comparison against NULL has never been required, it just happened to work when the operator returned a void*.
My guess is this (if(dFile==NULL){) if condition is trying to check whether a file was open successfully for writing, if so you use function is_open which is available in c++. So simply replace the condition by if (dFile.is_open()). This should do the trick.
Without knowing the rest of the code, you can just try to rephrase that line such as:
if(!dFile)
See what happens next.

pow() from math.h library - How to Apply using functions

So I'm writing a bit of code that needs to raise a function's return value to a certain power. I recently discovered that using the '^' operator for exponentiation is useless because in C++ it is actually an XOR operator or something like that. Now here's the code I want to write:
int answer = pow(base, raisingTo(power));
Now can anyone tell me if this is right? I'll explain the code. I've declared an int variable answer as you all are aware of, and initialized it to the value of any variable called 'base', raised to the return value of the raisingTo() function acting on any other variable called 'power'. When I do this (and I edit & compile my code in Visual C++ 2010 Express Edition), a red dash appears under the word 'pow' and an error appears saying: "more than one instance of overloaded function 'pow' matches the argument list"Can someone please solve this problem for me? And could you guys also explain to me how this whole pow() function actually works, cos frankly www.cplusplus.com references are a little confusing as I am still only a beginner!
The documentation states it pretty explicitly already:
The pow(int, int) overload is no longer available. If you use this overload, the compiler may emit C2668 [EDIT: That's the error you get]. To avoid this problem, cast the first parameter to double, float, or long double.
Also, to calculate basepower you just write
pow(base, power)
And with above hint:
int result = (int) pow((double)base, power);
The pow() function returns either a double or a float, so the first step would be to change answer to one of those. Second, what is raisingTo() returning. Unless your are doing something that's not evident, you don't need that, but it should still work. Also, both arguments should be doubles, according to this.

What is the preferred way in C++ for converting a builtin type (int) to bool?

When programming with Visual C++, I think every developer is used to see the warning
warning C4800: 'BOOL' : forcing value to bool 'true' or 'false'
from time to time. The reason obviously is that BOOL is defined as int and directly assigning any of the built-in numerical types to bool is considered a bad idea.
So my question is now, given any built-in numerical type (int, short, ...) that is to be interpreted as a boolean value, what is the/your preferred way of actually storing that value into a variable of type bool?
Note: While mixing BOOL and bool is probably a bad idea, I think the problem will inevitably pop up whether on Windows or somewhere else, so I think this question is neither Visual-C++ nor Windows specific.
Given int nBoolean; I prefer this style:
bool b = nBoolean?true:false;
The following might be alternatives:
bool b = !!nBoolean;
bool b = (nBoolean != 0);
Is there a generally preferred way? Rationale?
I should add: Since I only work with Visual-C++ I cannot really say if this is a VC++ specific question or if the same problem pops up with other compilers. So it would be interesting to specifically hear from g++ or users how they handle the int->bool case.
Regarding Standard C++: As David Thornley notes in a comment, the C++ Standard does not require this behavior. In fact it seems to explicitly allow this, so one might consider this a VC++ weirdness. To quote the N3029 draft (which is what I have around atm.):
4.12 Boolean conversions [conv.bool]
A prvalue of arithmetic, unscoped
enumeration, pointer, or pointer to
member type can be converted to a
prvalue of type bool. A zero value,
null pointer value, or null member
pointer value is converted to false;
any other value is converted to true.
(...)
In the context of using win32 SDK and MFC, I tend to write it always this way. It's explicit.
bool b = (myBOOL != FALSE);
EDIT: I have edited :-) cause i'm not sure myBOOL == TRUE works for all implementation of BOOL
and I can assume that FALSE may have the 0 value most of the time.
The correct way I'd assume is:
bool b = static_cast<bool>(val);
Three good ways:
static_cast<bool>( whatever )
bool( whatever )
!!whatever
Personally I prefer the last, but *nix folks may react negatively (not needed for those compilers, so not familiar with that idiom).
One reason that the last one is good is that it shuts up Visual C++ (sillywarning suppression).
Ungood ways include comparing with true or false, especially the former.
Cheers & hth.,
I cast my vote for
BOOL nBoolean;
bool b = (nBoolean != 0);
Reason? Since BOOL resolves to an int, one should compare it to an int when converting to bool. The other two methods: !!nBoolean and nBoolean?true:false treat nBoolean as as logical value and therefore perform an implicit cast conversion.
I tend to write it always this way. .
bool b = !!myBOOL;
It is clearer (well as an English speaker, I am used to double-negatives....)
It is also safer and avoids mistakes like:
bool b = (myBOOL = FALSE); //oops!
Also, I am of the opinion that booleans should never be compared using == or != rather && should be used. As soon as == or != is used the boolean variable is no longer treated as a boolean but as an integral value which defeats the purpose of boolean.
There is no preferred way in C++, since the C++ Std simply allows the integral conversion from int to bool. (So the preferred way wrt the Std would be bool b = i;.)
That said, judging from the other answers, there does not even seem to be an accepted way to do it in Visual C++ (MS) although the MSDN page states
... If you cannot rewrite the expression
to use type bool, then you can add
"!=0" to the expression, which gives
the expression type bool. ...
So one might conclude that MS recommends to use the !=0 comparison, although I, personally, think it's the worst of all the warning-supressing alterantives presented in the question and the answers here: The "type" in the source code is BOOL, and even though it's really just an int at least one should compare a "BOOL" with !=FALSE like has been proposed in some other answers.
If this bothered me, I would write a helper function like
inline bool to_bool(BOOL b) {...}
which would hide one of the proposed implementations inside it. And never think about this again :)

what errors will report if I overload operators incorrectly?

I know that we can't overload operator with other meaning, we can't create new operators, and we can't overload without user-defined class. If I overload operators incorrectly? what errors will report? compiler errors or runtime error?
If I overload **, what would happen?
You can overload only existing operators. There is no operator ** in C++.
If you try, the compiler would complain.
Operator overloads are checked at the compile time. If it compiles, it's just a kind of function, so the possible runtime errors are the same as for any other function.
Perhaps I'm misunderstanding your question, but you can definitely overload operators with different meanings. Consider integers vs iostreams:
1 << 5; // takes the value 1 and does a binary shift
cout << "moo"; // inserts the string "moo" into the cout stream
Anyway, operator overloads are just functions. Depending on what you do, you may get a compile error or a runtime error. It depends on the specific error.
Also, keep in mind that if you are manipulating objects on the heap (via the new operator), incorrectly overloading operators can cause crashes or memory leaks, as well as just not doing what you intended. These types of problems may not generate runtime or compile time errors.