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

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.

Related

What might be the intention of printing a stream to itself?

I am attempting to build a third-party C++ code base in which there are several places where an attempt is made to print an output stream to itself. This example demonstrates an expression of the same form:
#include <iostream>
int main(void) {
std::cout << std::cout << "Say what?" << std::endl;
return 0;
}
I find that without any options, g++ 4.8.5 accepts that code with zero complaints, but g++ 8.2.1 rejects it with a good old "no match for ‘operator<<’" error.
I understand the error. What I want to know is whether there is any reason to think that it was ever anything other than an error -- was there a C++ version or a widely used C++ compiler that would do something useful with such code? Although it accepts the code, g++ 4.8.5 is not such a compiler in my book because the program it builds evaluates the first << operation simply by outputting a hexadecimal number of unclear significance.
I have considered that it might be a simple typo, maybe magnified by copy & paste. For example, perhaps the second std::cout was an accidental duplicate of the first, or perhaps it was meant to be std::endl, instead. However, in a different source file in the same code base I see the same idiom of an output stream being printed to itself applied to objects of type std::stringstream, which suggests to me that it might be intentional.
My overall objective is to decide how best to fix the code.
What might be the intention of printing a stream to itself?
It is probably unintentional, or the intention itself was a mistake.
The difference between the GCC versions is the default dialect of C++ that they use. The newer GCC defaults to c++11 or newer. The program should compile with the newer compiler as long as you use a pre-C++11 dialect.
The change in C++11 was the removal of implicit conversion from std::basic_ios to void*. The purpose of this conversion was to check for failure state of the stream: null signified a failed stream while non-null signified a valid stream which allows the pattern if(stream >> input). In C++11 the conversion was replaced with explicit conversion to bool. Since the new conversion is explicit, it won't be applied to inserting a stream into stream. This was a backwards incompatible change which was presumably considered to not be a problem since the now-incompatible ways of using the conversion (such as the example) would have had no practical uses. In fact, it is useful to get a compilation error when doing something that has no practical use.
My overall objective is to decide how best to fix the code.
Probably just remove the insertion of cout into cout. If you're concerned that the output must remain same because it might be parsed by another program, then you can output any non-zero hex number to keep the output same for the sake of compatibility.

How to enable C++ warnings for bitwise operators with boolean arguments

While working with a rather large C++ code base and the GCC toolchain on Linux, I have encountered code which performs a boolean check as follows:
#include <stdio.h>
int main() {
bool foo = true;
if (~foo) {
// do some expensive operation
printf("This can be bad...\n");
}
return 0;
}
This looks like an obvious bug, since the ~ operator represents bit-wise NOT in C++, and not logical NOT, as it would, say, in MATLAB. The above code would always evaluate to true
Luckily, the issue caused by this bug was not major (it was just a small performance hit), but it got me thinking about how this bug hadn't been found in so much time.
Since the bit-wise operator triggers an implicit cast from the boolean to an integer, which is a promotion, there's nothing wrong with it per se. However, to me it seems as though at least something like clang-tidy should be able to pick this up as a logical error, since it is pretty clear that in most cases, the intent is not to apply a bit-wise operation to a bool, but instead a logical one.
g++ doesn't seem to care about this issue even with -Wall -Wextra -Wconversion enabled, which is sensible given that, as I mentioned before, this isn't against the standard. (I even tried g++ 6.3, which should have a lot of new checks, and still got nothing.)
Using clang-tidy with all checks enabled (which can get really noisy really fast) does warn about the implicit conversion itself ("implicit cast bool -> 'int'"), but there doesn't seem to be a specific warning related to applying bit-wise operators to booleans.
Writing the if-statement differently as if(~foo == true), while verbose and leading to an always-false scenario, does lead to more meaningful errors which can bring the bug into attention, but this doesn't happen when the terser if(~foo) form is used.
Are there any ways/tools to check for such issues, which are 100% correct C++, but very likely bugs?
There is -Wbool-operation in gcc as of gcc 7:
Warn about suspicious operations on expressions of a boolean type. For instance, bitwise negation of a boolean is very likely a bug in the program. For C, this warning also warns about incrementing or decrementing a boolean, which rarely makes sense. (In C++, decrementing a boolean is always invalid. Incrementing a boolean is invalid in C++1z, and deprecated otherwise.)
This warning is enabled by -Wall.
It provides the following warning for your program:
prog.cc:6:9: warning: '~' on an expression of type bool [-Wbool-operation]
if (~foo) {
^~~
prog.cc:6:9: note: did you mean to use logical not ('!')?
gcc demo
Unfortunately it does not appear that clang 5 has such an option. Even turning on (quite nearly) all of the possible warnings listed here, we still don't get the expected warning (Demo) (although we do get a few interesting others).
Finally, for completeness, MSVC 19.00.23506 definitely warns (Demo) (credit to #cbuchart for pointing this out):
source_file.cpp(8): warning C4804: '~': unsafe use of type 'bool' in operation

Is operator void*() conversion still part of C++ library?

Consider this program:
#include <iostream>
int main()
{
delete std::cout;
}
AFAIK the conversion function operator void* () const has been removed from C++11. So, this program should fail in compilation on a C++11 compiler. Ya, its true that both g++ 4.8.1 & 4.9.2 gives diagnosis (in the form of warning that deleting void* is undefined & that's also the good thing). But shouldn't this program fail in compilation because removal of that conversion function due to which all stream object could be implicitly converted to void* in C++98 & C++03?. Is this bug? It seems bit surprising that they still not have implemented this change.
I've tried this program in g++ 4.9.2(that supports C++14) but it gives warning not compiler error. Ideone compiler gives me an error as expected. (See live demo here)
It has nothing to do with the compiler, its a library issue. libstdc++ has lots of incompatibilities with C++11, of which this is just one. They are making breaking changes in 5 and up though iirc.
In short, it's neither a bug nor a compiler issue.
This is a bug in the standard library (if you view it as an implementation of the C++11/14 standard library rather than C++98/03).
It's sort of a compiler issue as well though. Specifically, removing the conversion to void * depends on adding a conversion directly to bool--but that, in turn, depends on adding "contextual conversion" to the compiler.
gcc 4.8 did implement a form of contextual conversion, but not the form that was accepted into the standard. Although the specific changes to contextual conversion wouldn't directly impact this use of contextual conversion, it does point to the fact that the definition of contextual conversion was still being tweaked as these compilers were being written.
The sequence in which things (at least normally) happen is that first the specification is solidified. Then the compiler implements it. Then the standard library puts it to use.
In this case the specification was still changing fairly shortly before the compiler was released. Therefore, the standard library didn't (and practically speaking, couldn't) use it.
By the time of 4.9, the specification was solid, and the compiler implemented the final version of contextual conversion, but it hadn't been around long enough to be put to use in the standard library yet.

I can't use if ( ifs == NULL) command in VS 2013

When compiling this code:
std::ifstream ifs("somefile.txt");
if(ifs == NULL)
I get an error
no operator matches these operands "=="
I got the same error in every project with VS 2013, but I didn't have any problem in VS 2010.
How to solve this?
The definition of std::basic_ios (from which std::basic_ifstream inherits) changed in C++11. In particular, it's conversion operator operator void* changed to explicit operator bool, so what you're trying to do is no longer valid. Nonetheless, it was never a common way to check the state of your stream. Instead, just do if (!ifs).
The C++ standard changes, now faster than ever, and MSVC has a habit of just mixing together the different standards until they fully support the latest one. You can expect some code to break when things change, although the committee aim to minimise this as much as possible.

Why do streams still convert to pointers in C++11?

The canonical way to read lines from a text file is:
std::fstream fs("/tmp/myfile.txt");
std::string line;
while (std::getline(line, fs)) {
doThingsWith(line);
}
(no, it is not while (!fs.eof()) { getline(line, fs); doThingsWith(line); }!)
This works beacuse std::getline returns the stream argument by reference, and because:
in C++03, streams convert to void*, via an operator void*() const in std::basic_ios, evaluating to the null pointer value when the fail error flag is set;
see [C++03: 27.4.4] & [C++03: 27.4.4.3/1]
in C++11, streams convert to bool, via an explicit operator bool() const in std::basic_ios, evaluating to false when the fail error flag is set
see [C++11: 27.5.5.1] & [C++11: 27.5.5.4/1]
In C++03 this mechanism means the following is possible:
std::cout << std::cout;
It correctly results in some arbitrary pointer value being output to the standard out stream.
However, despite operator void*() const having been removed in C++11, this also compiles and runs for me in GCC 4.7.0 in C++11 mode.
How is this still possible in C++11? Is there some other mechanism at work that I'm unaware of? Or is it simply an implementation "oddity"?
I'm reasonably certain this is not allowed/can't happen in a conforming implementation of C++11.
The problem, of course, is that right now, most implementations are working on conforming, but aren't there completely yet. At a guess, for many vendors, this particular update is a fairly low priority. It improves error checking, but does little (or nothing) to enable new techniques, add new features, improve run-time efficiency, etc. This lets the compiler catch the error you've cited (some_stream << some_other_stream) but doesn't really make a whole lot of difference otherwise.
If I were in charge of updating a standard library for C++11, I think this would be a fairly low priority. There are other changes that are probably as easy (if not easier) to incorporate, and likely to make a much bigger difference to most programmers.
To use one of the examples you gave, if I were in charge of updating the VC++ standard library to take advantage of the compiler features added in the November CTP, my top priority would probably be to add constructors to the standard container types to accept initialization_lists. These are fairly easy to add (I'd guess one person could probably add and test them in under a week) and make quite an obvious, visible difference in what a programmer can do.
As late as GCC 4.6.2, the libstdc++ code for basic_ios is evidently still C++03-like.
I'd simply put this down to "they haven't gotten around to it yet".
By contrast, the libc++ (LLVM's stdlib implementation) trunk already uses operator bool().
This was a missed mini-feature buried in a pre-existing header. There are probably lots of missing error of omission and commission in pre-2011 components.
Really, if anyone comes up with things like this in gcc then it would do a world of good to go to Bugzilla and make a bug report. It may be a low priority bug but if you start a paper trail
I'll go out on a limb and extend this idea to all the other C++ compilers: clang, Visual Studio,etc.
This will make C++ a better place.
P.S. I entered a bug in Bugzilla.