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

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.

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.

Compare ptr with nullptr in gtest

Have some code:
EXPECT_NE(nullptr,ptr);
And I get the following compilation error:
'operator <<' is ambiguous
could be 'std::basic_ostream<char,std::char_traits<char>> &std::basic_ostream<char,std::char_traits<char>>::operator <<<void>(std::nullptr_t)'
or 'std::basic_ostream<char,std::char_traits<char>> &testing::internal2::operator <<<char,std::char_traits<char>,T>(std::basic_ostream<char,std::char_traits<char>> &,const T &)'
Could this be a library version problem?
If you want to be more explicit, you could also use
EXPECT_TRUE(ptr != nullptr);
(that's what I normally do)
Btw. funnily enough, in my work project I still have to work with C++98 (still building for Sun and AIX, although it will soon go away) and I ended up creating my own NullPtrT class and NullPtr object in the common library, which actually works with gtest EXPECT_EQ and EXPECT_NE macros. So that I can do
EXPECT_NE(NullPtr, ptr);
I don't remember how exactly I made that work :)
I've run into the same problem recently with GTest 1.8.0, but only when using Visual Studio 2019 in C++17 mode. Visual Studio 2019 works fine in C++14 mode, and neither Clang nor GCC seem to have the same problem in C++17 mode.
The issue is that with C++17 there's a new overload in the standard library for the std::ostream::operator<< that takes a nullptr_t, but GTest also provides its own, so your compiler does not know which one to use.
If you have full control over your version of GTest then https://github.com/google/googletest/pull/1620/commits/f66ab00704cd47e4e63ef6d425ca14b9192aaebb is a change for GTest-1.8.0 that resolves the issue: It's not as easy as deleting the overload, because the function in question is a template whose other instantiations are still used. Instead, the solution is to define an explicit void PrintTo(std::nullptr_t, ::std::ostream* os) function that will then automatically be used, no longer deferring to the ambiguous overloads.
When modifying GTest is not an option then the solutions mentioned in the other answers to not use EXPECT_EQ/EXPECT_NE when one parameter is a nullptr_t are your best bet.
namespace {
template<class T>
auto not_nullptr(T*p) -> testing::AssertionResult
{
if (p)
return testing::AssertionSuccess();
else
return testing::AssertionFailure() << "pointer is null";
}
}
...
EXPECT_TRUE(not_nullptr(ptr));
reference:
https://github.com/google/googletest/blob/master/docs/advanced.md#using-a-function-that-returns-an-assertionresult
Google Test documentation says that,
When comparing a pointer to NULL, use EXPECT_EQ(ptr, nullptr)
instead of EXPECT_EQ(ptr, NULL)
When comparing a pointer to NULL, use EXPECT_NE(ptr, nullptr)
instead of EXPECT_NE(ptr, NULL).
Therefore, you can just use EXPECT_NE(ptr, nullptr);.
Read more: https://google.github.io/googletest/reference/assertions.html#EXPECT_NE
#include "gtest.h"
using ::testing::NotNull;
ASSERT_THAT(ptr, NotNull());
This will give you some more descriptive errors and keeps you using the existing framework. Other benefits are compatibility with smart pointers and raw pointers.
Other matchers can be found on the gtest matchers documentation.

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.

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.

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.