C++ conversion operator - c++

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.

Related

Do all C++ operators return something?

All C++ operators that I have worked with return something, for example the + operator returns the result of the addition.
Do all C++ operators return something, or are there some C++ operators that do not return anything?
No, not all operators return something.
Although they are probably not exactly what you are thinking about, note that the delete and delete[] C++ 'keywords' are actually operators; and they are defined as having the void return type - which means they evaluate to nothing (which is not 'something').
From cppreference:
void operator delete ( void* ptr ) noexcept;
void operator delete[]( void* ptr ) noexcept;
Operators of custom types can be overloaded to do the most weirdest things.
for example the + operator returns the result of the addition.
Not necessarily:
#include <iostream>
struct foo {
int value = 0;
void operator+(int x) {
value += x;
}
};
int main () {
foo f;
f + 3;
}
Here operator+ adds the left hand side to the value member, and its return type is void. This is a made-up example, but, in general, not returning something from a custom operator is not unusual.
The only operator that can be overloaded and that has the requirement of returning something, that I am aware of, is operator->. It must either return a raw pointer or an object that has an operator->.
To nitpick, operators don't return anything. They are just lexical elements that we use to create expressions in the language. Now, expressions have types and may evaluate to values, and I assume this is what you mean by operators "returning things".
And, well, yes. There are C++ expressions with type void (and consequentially don't evaluate to any value). Some are obvious, others less so. A nice example would be
throw std::runtime_error()
throw is an expression under the C++ grammar. You can use it in other expressions, for instance in the conditional expression
return goodStatus() ? getValue() : throw std::runtime_error();
And the type of a throw expression, is void. Obviously since this just causes execution to rapidly go elsewhere, the expression has no value.
None of the built-in C++ operators return something. Overloaded C++ operators return something insofar that the operator notation is a syntactic sugar for a function call.
Rather, operators all evaluate to something. That something has a well-defined value as well as a type. Even the function call operator void operator()(/*params*/) is a void type.
For example, +'a' is an int type with the value of 'a' encoded on your platform.
If your question is "Can C++ operators have a void return type?" then the answer is most certainly yes.
You can actually define a function call operator to return nothing. For example:
struct Task {
void operator()() const;
};
operator void(): user defined conversion function to void
You may define the peculiar operator void() conversion function, where the compiler will even warn you that the T to void conversion function will never be used:
#include <iostream>
struct Foo {
operator void() { std::cout << "Foo::operator void()!"; }
// warning: conversion function converting 'Foo' to
// 'void' will never be used
};
int main() {
Foo f;
(void)f; // nothing
f.operator void(); // Foo::operator void()!
}
as governed by [class.conv.fct]/1
[...] A conversion function is never used to convert a (possibly
cv-qualified) object to the (possibly cv-qualified) same object
type (or a reference to it), to a (possibly cv-qualified) base class
of that type (or a reference to it), or to (possibly cv-qualified)
void.117
(117)
These conversions are considered as standard conversions for the
purposes of overload resolution ([over.best.ics], [over.ics.ref]) and
therefore initialization ([dcl.init]) and explicit casts. A
conversion to void does not invoke any conversion function
([expr.static.cast]). Even though never directly called to perform a
conversion, such conversion functions can be declared and can
potentially be reached through a call to a virtual conversion function
in a base class.
Whilst, however, as is shown above, you can still invoke it using the explicit .operator void() syntax.
The operators defined (builtin) by the language are tokens used to perform different kinds of computations:
arithmetic (+,-,*,/)
increment/decrement (++,--)
assignment (=,+=,-=,*=,/=,%=,>>=,<<=,&=,^=,|=)
logic (!,&&,||)
relational (==,!=,>,<,>=,<=)
conditional ?
comma
and so on. The list can be very extensive.
In language references like this one or this one, these are not necessarily referenced as returning something, just performing an arithmetic or logic operation, a comparison by which means a variable may be modified, etc.
Since this operation results in some value, it may be interpreted as been "returned" by the operator, but it is different from a function return value.
The overloaded operators, on the other hand, can be defined with a return value of some type, even that can be void, so, no, not all operators return some value in C++.
I'm assuming you're talking about operator functions and not operators as a syntactic unit of the language.
If you overload operators on any type, you may actually return whatever you want.
This also makes a lot of sense, because operations like * or () may sometimes very intuitively not return their input type. Imagine multiplying a complex number type with a real number type. Or an operator that returns an element from a collection.
You may also overload the ++ and -- operators to not return anything thus removing the extremely error-prone mixing of side-effect and expression value that the standard version has.
No.
Consider these two examples here:
int multiply (int a, int b) {
return a*b;
}
void multiply_void(int a, int b) {
cout << a*b;
//or cout << multiply(a,b);
}
First function will return an integer value which can be used by another function.
The value is returned and stored in memory to be used when necessary. If not, it is not visible to human & just sits happily in the memory.
Second function will output to the default output device(usually console).
The value returned by the multiplication operator is passed to an output device.
The function multiply_void does not return an actual value.
All operators return something. They are called operators because they operate something , therefore they will return something. Those Operators who do not return something cant be called operators. Either they will return some value or return True or False depending upon the situation.
Operators on their own do not necessarily return anything. Function calls return values. Operators can result in values.
Operators can sometimes invoke functions. Examples include:
• The function call operator.
• An overloaded operator that gets transformed into a function call.
• operator new, which is invoked as part of a new-expression, is a function call.
My only purpose in mentioning function calls is to clarify the result vs. return. Based on looking at all 126 instances of “return” and words derived from it in [expr], the section seems to carefully use the word return to refer to:
• the result of a function call
• aspects of control flow related to coroutines
OK, that’s enough pedantry on result vs. return.
C++ Operators return something or not is depends upon how you used them. Built-In C++ operators return some value until and unless enforced to return void.

`ofstream` compared to 0

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;

What does (void *)1 mean?

I'm reading the code of ROS.
In the file ros_comm/roscpp/include/ros/subscriber.h, I see such a piece of code:
operator void*() const { return (impl_ && impl_->isValid()) ? (void*)1 : (void*)0; }
Well, (void *)0 can be regarded as NULL in C, but what does (void *)1 mean?
If a class Foo contains this function, it means that we can code like this:
Foo foo;
void *ptr = foo;
Right? So does it mean that void *ptr = (void *)1 is possible? What does this mean?
This is an old trick to avoid problems with implicit conversions to bool from before explicit contextual conversions were introduced in C++11. It's intended to be used to check validity:
Subscriber my_subscriber = someFunction();
if (!my_subscriber) {
// error case
}
The important point is that no built-in conversion exists from void* to integer types, but one does exist from bool to integer types. At the same time, a built-in conversion from void* to bool exists. That means that if you define an implicit conversion to bool, then the following is surprisingly valid:
void my_func(int i);
void another_func() {
Subscriber sub = something();
my_func(sub);
}
Defining a conversion to void* avoids that issue.
These days that trick is obsolete though. C++11 introduced explicit conversions. explicit conversions to bool are considered in the conditions of if and loops, but aren't considered in other problematic cases. That means that these days that conversion should be written as:
explicit operator bool() const { return impl_ && impl_->isValid(); }
It shows that either the person who wrote the code isn't very well acquainted with the language or tools they're using, or the code has been around for a long, long time and been hacked on by different people, presumably having undergone a C-to-C++ transition at some time in the past, still carrying some legacy API contract (expecting a void*) which may be troublesome to change.
There is no good reason to do such a thing, if you look at the source. impl_ is a boost::shared_ptr<Impl> which implements operator bool, and Impl::isValid returns bool, too. There's no reason to use, or return anything but bool anywhere.
Basically, this is a contorted (and possibly dangerous) way of writing:
return impl_ && impl_->isValid();

Output of void pointer function

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.

Is using void* instead of bool an advisable practice?

Horstmann’s C++ pitfalls tackles an interesting point when talking about streams. To quote him:
Use conversion to void*, not conversion to int or bool, to implement objects yielding truth values. Unlike int or bool, void* have no legal operations other than == comparison.
As a programmer, I would be puzzled if some function returned void* when I expect a boolean. Horstmann provides an example where using a void* instead of a bool seems appropriate. Is it always advisable?
This is not advised in general circumstances and, with C++11, is not advised at all.
The reason for the conversion to void* was to support syntax like
std::ifstream myStream;
if (myStream) {
}
if (!myStream) {
}
Here, a conversion to bool seems more reasonable, but leads to weirdnesses like this:
if (myStream == true) // ??
The conversion to void* prevents this code from being legal, but opens up a whole other can of worms, like
delete myStream; // ??
In C++11, with the ability to have explicit operator bool() as a member function, this void* hack is deprecated and should not be used. Don't use this idiom. If you need something to return a bool, have it return a bool. If you need an object that can be converted to a bool, use explicit operator bool.
Hope this helps!