How does calling class name Serial# return a value?

All of the HardwareSerial class instantiations (i.e. Serial, Serial1, etc) can be directly called by name and return a bool based on whether or not the port is connected/initialized. I've been looking at HardwareSerial.cpp and HardwareSerial.h to figure out how this was implemented, but I can't quite figure it out.

Here is the HardwareSerial.h file I'm looking at:

// ArduinoCompat/HardwareSerial.h
// STM32 implementation of Arduino compatible serial class

#include <RadioHead.h>
#if (RH_PLATFORM == RH_PLATFORM_STM32STD)
#ifndef _HardwareSerial_h
#define _HardwareSerial_h

#include <stdint.h>
#include <stdio.h>
#include <stm32f4xx.h>

#ifndef ARDUINO_RINGBUFFER_SIZE
#define ARDUINO_RINGBUFFER_SIZE 64
#endif

class RingBuffer
{
public:
    RingBuffer();
    bool    isEmpty();
    bool    isFull();
    bool    write(uint8_t ch);
    uint8_t read();

private:
    uint8_t _buffer[ARDUINO_RINGBUFFER_SIZE]; // In fact we can hold up to ARDUINO_RINGBUFFER_SIZE-1 bytes
    uint16_t _head;      // Index of next write
    uint16_t _tail;      // Index of next read
    uint32_t _overruns;  // Write attempted when buffer full
    uint32_t _underruns; // Read attempted when buffer empty
};

// Mostly compatible wuith Arduino HardwareSerial
// Theres just enough here to support RadioHead RH_Serial
class HardwareSerial
{
public:
    HardwareSerial(USART_TypeDef* usart);
    void begin(unsigned long baud);
    void end();
    virtual int available(void);
    virtual int read(void);
    virtual size_t write(uint8_t);
    inline size_t write(unsigned long n) { return write((uint8_t)n); }
    inline size_t write(long n) { return write((uint8_t)n); }
    inline size_t write(unsigned int n) { return write((uint8_t)n); }
    inline size_t write(int n) { return write((uint8_t)n); }

    // These need to be public so the IRQ handler can read and write to them:
    RingBuffer     _rxRingBuffer;
    RingBuffer     _txRingBuffer;

private:
    USART_TypeDef* _usart;

};

// Predefined serial ports are configured so:
// Serial       STM32 UART   RX pin   Tx Pin   Comments
// Serial1      USART1       PA10     PA9      TX Conflicts with GREEN LED on Discovery
// Serial2      USART2       PA3      PA2
// Serial3      USART3       PD9      PD10     
// Serial4      UART4        PA1      PA0      TX conflicts with USER button on Discovery
// Serial5      UART5        PD2      PC12     TX conflicts with CS43L22 SDIN on Discovery
// Serial6      USART6       PC7      PC6      RX conflicts with CS43L22 MCLK on Discovery
//
// All ports are idle HIGH, LSB first, 8 bits, No parity, 1 stop bit
extern HardwareSerial Serial1;
extern HardwareSerial Serial2;
extern HardwareSerial Serial3;
extern HardwareSerial Serial4;
extern HardwareSerial Serial5;
extern HardwareSerial Serial6;

#endif

#endif

Maybe it has something to do with this this?

public:
    HardwareSerial(USART_TypeDef* usart);

A bit different than the HardwareSerial.h file I have installed, but the magic is in overloading the bool operator

operator bool() { return true; }

Hmmm, I'm still not getting it. I understand overloading functions, but not in this specific context.

How does

operator bool() { return true; }

allow me to do

while(!Serial);

The return of Serial isn't always true, so there must me more to the story...

I imagine @blh64's code was just a simple illustration of overloading 'operator bool()'. The code inside the {} could be anything the class needs to do for determining whether to return 'true' or 'false'.

In many cases, the code is exactly as blh64 provided. The reason is that it's only possible to detect a connection on the CDC serial ports (e.g., Serial on Leonardo). It is not possible to do this on the hardware serial ports (e.g., Serial on Uno). On those boards, it will always return true.

You can see the code used for Serial on the ATmega32U4 boards here:

// This operator is a convenient way for a sketch to check whether the
// port has actually been configured and opened by the host (as opposed
// to just being connected to the host).  It can be used, for example, in 
// setup() before printing to ensure that an application on the host is
// actually ready to receive and display the data.
// We add a short delay before returning to fix a bug observed by Federico
// where the port is configured (lineState != 0) but not quite opened.
Serial_::operator bool() {
 bool result = false;
 if (_usbLineInfo.lineState > 0) 
 result = true;
 delay(10);
 return result;
}

pert:

Serial_::operator bool() {

}

Ahhhh, that makes a lot more sense. Thanks!