I'm upgrading existing old code to use VS 2019*, in the code I have the following function that fails on the return line:
int foo(const char *fn) const
{
ofstream out(fn,ios::binary);
if (out)
{
//...
}
return out!=0;
}
The error I get is:
Error C2678 binary '!=': no operator found which takes a left-hand operand of type 'std::ofstream' (or there is no acceptable conversion)
What was the original poet's intention, and what is the best way to fix the issue?
*This code compiles successfully on VS 2010.
I suppose with the upgrading, you're switching to C++11 mode.
Before C++11, std::basic_ios (the base class of std::basic_ofstream) could convert to void* implicitly.
Returns a null pointer if fail() returns true, otherwise returns a non-null pointer.
Then out!=0 is checking whether the stream has no errors and is ready for further I/O operations.
Since C++11, there's only one conversion operator which could convert std::basic_ios to bool. Note that the operator is marked as explicit, so the implicit conversion isn't allowed for out!=0.
You can change the code to !!out (invoking operator!), or !out.fail(), or static_cast<bool>(out) (explicit conversion via operator bool).
There are two operators in the class std::basic_ios that can be applied in such a situation. They are
explicit operator bool() const;
bool operator!() const;
So you can for example either write
return bool( out );
or
return !!out;
or
return !out != true;
Related
I have unearthed an old C++ DLL, and I'd like to us it in one of my projects, in VS2015.
The problem is, it does not compile. I got in touch with a guy in the team that made the code in the first place, and he is positive that the exact same code compiled with VS2010.
I have an error in an otherwise very simple function:
Extract of header:
/*
Data input
*/
istream* input; //Source of data
long inputpos; // Current position in the data stream
And the code itself:
// Helper function to increment a counter while reading a character
void* Calculator::inputstream_get(char& ch)
{
++inputpos;
return input->get(ch);
}
In the end, I get an Error C2440:
'return': cannot convert from 'std::basic_istream<char,std::char_traits<char>>' to 'void *'
It is my understanding (I'm not a C++ expert I have to say...) that void pointers could represent any type of data, am I mistaken?
Is there any way to 'cast' my istream to an void pointer?
Thanks a lot for your help
The reason why this compiles in VS 2010 (C++03) and not in VS 2015 (C++11) is that in C++03, standard library streams defined an implicit conversion to void*; the purpose of that conversion was to allow testing them for truthiness (such as while (cin >> x)) without allowing an implicit conversion to bool (which would allows such monstrosities as 1 + (cin >> x) to compile).
Note that the value of the returned void* was underspecified: it was either a null pointer when the stream is in a failed state, or an unspecified non-null pointer when the stram's in good state.
C++11 introduced the notion of explicit conversion operators and contextual conversion to bool, which means that these "hacky" conversions to void* were replaced in the standard by a safe explicit operator bool () const. Of course, this makes the code fail to compile as C++11.
How you can solve this is change Calculator::inputstream_get as follows:
void* Calculator::inputstream_get(char& ch)
{
++inputpos;
return input->get(ch) ? this : nullptr;
}
This preserves the semantics of returning a null pointer on failure, and an unspecified non-null pointer on success.
To answer your last question. You cannot cast a non pointer to a pointer. But you can cast any pointer to a void pointer with (void*)
This is the deal. http://en.cppreference.com/w/cpp/io/basic_ios/operator_bool
In C++03 that was operator void* and in C++11 that is operator bool.
Change that void* to bool. Note that after the change the code will be not usable in C++03 compiler. You can solve it in a portable fashion with
if (input->get(ch)) return true;
else return false;
Actually, the most proper way is to return reference to the actual istream object.
I am compiling an outdated project with my latest gcc g++ compilers, (version > 6)
There is a class CodeWriter with an ostream reference variable.
class CodeWriter
{
//private:
protected:
ostream &m_stream;
public:
CodeWriter(ostream &stream):m_stream(stream){}
~CodeWriter(){
if(m_stream != NULL){
m_stream.flush();
}
}
};
The class is quite large so I included only the relevant variables and functions.
As you can see the destructor seems to be comparing the reference to NULL.
This project compiled fine when I used it long back with old gnu toolchain.
But now it is throwing an error saying that there is no matching operator != to compare ostream and long int.
Can anyone explain the rationale behind the change, and how I can fix this?
I would be happy to provide additional information/ include the whole class if required.
The code is not comparing the reference itself with NULL, but comparing the referenced-object with NULL. References can't be NULL, and it's impossible to compare the reference itself with NULL.
And
This project compiled i when i used it long back with old gnu toolchain.
Because the behavior changed since C++11.
Before C++11, std::ostream could be implicitly converted to void* via operator void*(), which returns a null pointer if error has occurred on the stream. So the original intent of the code is to check whether the stream has no errors.
Since C++11 the conversion function was changed to explicit operator bool(), which returns false if error has occured. Note the function is declared as explicit, which means implicit conversion to bool is not allowed, so the code won't compile with C++11 again because std::ostream can't be converted to bool implicitly (and then to be compared with NULL (an integer literal)).
With a C++11-compatible compiler you can just change the code to
if (m_stream) {
m_stream.flush();
}
Note that for contextual conversions even explicit conversion functions are considered. For the above code, m_stream will be converted to bool via explicit operator bool(), then the value would be used for the condition of if.
Streams can always be evaluated in a boolean context, so just change it to:
if (m_stream) {
m_stream.flush();
}
C++11 made the conversion to bool explicit. This is equivalent to if (!m_stream.fail()). Prior to C++11, this short-hand checkability was achieved by providing an (implicit!) conversion to void*, which is why your old code used to work.
The reason the code is checking for this, rather than just calling m_stream.flush(); directly, is perhaps that the stream may have exceptions enabled for failure and that might throw, [update:] but, as #Arne pointed out, flush itself may fail and throw, too. If there are no exceptions, you can just skip the boolean check entirely.[/update]
The stream classes had an operator void*() in one of the base classes in pre-C++11. Of course the void* value could be compared to NULL.
In current C++ this is instead an explicit operator bool() which works in the context of the if statement, but not in a general expression.
The use of a void* was to avoid some unwanted conversions from bool that happened when we didn't have explicit operators.
What does the code below intended to do?
return cin==(cout<<(f(a)==f(b)?"YES":"NO"));
assume f() is a string returning function and a and b are strings as well and function's signature is
string f(string a)
Thanks in advance!
The answer is: it depends on what C++ standard you're compiling against. It boils down to the conversion functions in std::basic_ios
C++03
Here, we have operator void*() const, which:
Returns a null pointer if fail() returns true, otherwise returns a non-null pointer. This pointer is implicitly convertible to bool and may be used in boolean contexts.
Thus, in the expression:
cin==(cout<<(f(a)==f(b)?"YES":"NO"));
we would print either "YES" or "NO", and the result of the stream output would be cout still (in the form of a std::ostream&). When we do the equality check, both operands would be implicitly converted to void* and so the expression checks to see if both streams failed. This is a particularly obfusticated way of doing:
cout << (f(a) == f(b) ? "YES" : "NO");
return cin.fail() && cout.fail();
C++11
With C++11, the operator void*() const is replaced by explicit operator bool() const. The explicit is key, as it means that the conversion function can only be used explicitly (as in, via a direct cast) or in a boolean context, as in:
if (cin) { // calls cin.operator bool()
}
Equality is not a boolean context, so in the expression
cin == cout
that conversion function will not be invoked. As there is no operator== defined on std::basic_ios (or std::istream or std::ostream), the expression will simply not compile.
In following code:
if ( cin >> x ) { /* ... */ }
the standard library define an operator conversion operator void*, which converts type istream to void*. However, if the if tests a condition, why the standard library doesn't define a conversion from type istream to type bool? Or is there any implicit consideration behind the implementation?
The simple reason is that you don't want to accidentally end up with a conversion to an int. For example, assume there is an implicit conversion to bool and you wrote
if (std::cin << x) { /* ... */ }
The compiler couldn't catch the obvious error (using << instead of >>) because the implicit conversion would convert to int and happily shift the result. That is almost certainly not what is intended. A void* can't be shifted, i.e., the compiler would yield an error instead.
Prior to C++11 there was no way to mark conversion operators explicit. You could only mark conversion constructors as explicit. In C++11 the conversion operator for streams was actually changed to an explicit conversion to bool as the conversion to void* had a few problems, too.
The operator bool() has always been a bit problematic. The main problem is that bool in C++ is an arithmetic operator, so any class that implements operator bool() will automatically be convertible to int.
Thus, the following code would be legal, but quite meaningless:
cout << (2 * cin);
The designers of the standard library thought that the operator less likely to cause problem, while at the same time being able to be converted to bool would be operator void*. The idea is that a void*, as is, cannot be used for anything.
That said, other more modern libraries, such as boost sometimes use the following idiom:
typedef void *this_type::*unspecified_bool_type;
operator unspecified_bool_type() const { return ... ; }
That is, instead of bool or void* they use a pointer-to-member-function, that will be truly useless other than being converted to bool.
That said, with C++11, the designers of the language noticed this problem and designed the following solution:
explicit operator bool() const
{ return ...; }
Now, this operator will only be called when the object is in a truly bool context (if, while...) , not in any random integral operation.
I am new to C++. recently I come across the following code
ifstream in("somefile");
if(in){
//read the file....
}
I am wondering which operator overloading the ifstream might have used for the in object to automatically evaluate to boolean in if condition. I tried but couldnt find a clue. please help me. thank in advance
It's actually operator void *.
It's overridden to return a non-zero pointer if the stream is valid, and a NULL pointer otherwise. The pointer it returns is meaningless and should not be dereferenced, it's only there to be evaluated in a boolean context.
The void pointer conversion operator is often used for this purpose. Something similar to
struct ifstream {
typedef void * voidptr;
operator voidptr() const;
};
std::ifstream gets its conversion to bool from it's base class std::ios (std::basic_ios<char>) which has conversion function declared:
explicit operator bool() const;
It returns !fail().
(In the previous version of the standard ISO/IEC 14882:2003, std::basic_ios had a conversion function operator void*() const but this version of the standard has now been withdrawn.)