You are here:

C++/About function prototype

Advertisement


Question
what does operator void * () mean?

where and how it can be used?

Answer
OK let's break it down:

void * is a type, a pointer to an unspecified type.

operator is a  keyword that introduces some sort of overloaded operator function, it is a function declaration as indicated by the ().

The operator keyword when followed by a type, such as int, bool, void* etc. rather than an operator such as + - = == etc. introduces a type conversion function. Such functions are non-static (i.e. instance) member functions of some class. They specify a conversion from the type of the class in which they are declared to the type given after the operator keyword.

So in this case the conversion is from the type of the class in which the declaration appears to void *.

The compiler will call such conversions implicitly to try to make the types used in expression make sense.

A common use of converting some class type to void * is to allow instances of the class to be tested, thus:

   class X
   {

   // ...

       operator void *() const; // declared here, defined elsewhere

   // ...

   };

   // ...

       X x;

   // ...    

       if ( x )
       {
       // Do something if x 'true'
       }

The reason conversion to void * is chosen rather than conversion to bool is that conversion to void * can still be used in Boolean expressions (a null pointer value is false; all other values are true), but cannot be converted to integer values. A conversion to bool however could lead to instances of x being used surprisingly and probably erroneously as an integer value 0 or 1. For example consider the following:

   #include <iostream> // for std::cout

   class X
   {
       int iV;

   public:
       explicit X(int v) : iV(v) {}

       operator bool() const { return iV < 10; }
   };

   int main()
   {
       X x1(1);
       X x2(-1);
       X x3(10);
       std::cout << "x1 is " << (x1 ? "true" : "false") << '\n';
       std::cout << "x2 is " << (x2 ? "true" : "false") << '\n';
       std::cout << "x3 is " << (x3 ? "true" : "false") << '\n';

       int xxx( x1 + x2 + x3 );
       std::cout << "xxx = " << xxx << '\n';
   }

The integer xxx is initialised to the sum of x1, x2 and x3. However these are of type class X, not an arithmetic type so what is going on? Class X has a conversion to bool that allows x1, x2 and x3 to be tested, as in the lines that output whether x1, x2 and x3 are true of false. However this conversion can also be used as if x1, x2 and x3  were 0 or 1 depending on whether the operator bool function returns false or true. For this example the logic of the bool conversion function is a bit spurious, the operator bool function for X returns true if the value that X instances are initialised with are less than 10. So x1 and x2 convert to true or 1 and x3 converts to false or 0. Thus xxx will be initialised to 1 + 1 + 0 or 2 and the output from the program should read:

   x1 is true
   x2 is true
   x3 is false
   xxx = 2

This additional usage as an integer that conversion to bool allows is generally undesirable as it will usually be erroneous usage. It would be nice if we could still get types to be testable but not also take part in arithmetic operations. This is what conversion to void* allows. By changing the type X can be converted to from bool to void* thus:

   class X
   {
       int iV;
   public:
       explicit X(int v) : iV(v) { }
       operator void *() const
       {
         return reinterpret_cast<void*>(iV<10);
       }
   };

The program xxx will fail to compile with an error such as:

   binary '+' : 'X' does not define this operator or a
   conversion to a type acceptable to the predefined operator

or:

   no match for 'operator+' in 'x1 + x2'

or similar for the line:

       int xxx( x1 + x2 + x3 );

Removing (or commenting out) this line and the following one that uses xxx so main contains the code:

   int main()
   {
       X x1(1);
       X x2(-1);
       X x3(10);
       std::cout << "x1 is " << (x1 ? "true" : "false") << '\n';
       std::cout << "x2 is " << (x2 ? "true" : "false") << '\n';
       std::cout << "x3 is " << (x3 ? "true" : "false") << '\n';
   }

allows the program to build and when executed produces the output:

  x1 is true
  x2 is true
  x3 is false

You will have noticed the I had to explicitly convert the bool result of the test of iV<10 in the operator void*() function to void*. This is because there is no implicit conversion from bool to void*.

You will also have noticed that I have specified the operator void* and operator bool conversion functions as a const member functions as they do not change the state of objects of class X.

An example of an operator void*() conversion function is in the C++ IOStreams library. C++ IO streams are convertible to void* so they may be tested directly to check there has not been a stream failure or unrecoverable error:

   if ( myStream )
   {
   // Stream not failed...
   }

Hope this helps.  

C++

All Answers


Answers by Expert:


Ask Experts

Volunteer


Ralph McArdell

Expertise

I am a software developer with more than 15 years C++ experience and over 25 years experience developing a wide variety of applications for Windows NT/2000/XP, UNIX, Linux and other platforms. I can help with basic to advanced C++, C (although I do not write just-C much if at all these days so maybe ask in the C section about purely C matters), software development and many platform specific and system development problems.

Experience

My career started in the mid 1980s working as a batch process operator for the now defunct Inner London Education Authority, working on Prime mini computers. I then moved into the role of Programmer / Analyst, also on the Primes, then into technical support and finally into the micro computing section, using a variety of 16 and 8 bit machines. Following the demise of the ILEA I worked for a small company, now gone, called Hodos. I worked on a part task train simulator using C and the Intel DVI (Digital Video Interactive) - the hardware based predecessor to Indeo. Other projects included a CGI based train simulator (different goals to the first), and various other projects in C and Visual Basic (er, version 1 that is). When Hodos went into receivership I went freelance and finally managed to start working in C++. I initially had contracts working on train simulators (surprise) and multimedia - I worked on many of the Dorling Kindersley CD-ROM titles and wrote the screensaver games for the Wallace and Gromit Cracking Animator CD. My more recent contracts have been more traditionally IT based, working predominately in C++ on MS Windows NT, 2000. XP, Linux and UN*X. These projects have had wide ranging additional skill sets including system analysis and design, databases and SQL in various guises, C#, client server and remoting, cross porting applications between platforms and various client development processes. I have an interest in the development of the C++ core language and libraries and try to keep up with at least some of the papers on the ISO C++ Standard Committee site at http://www.open-std.org/jtc1/sc22/wg21/.

Education/Credentials

©2016 About.com. All rights reserved.