C++ - useful magic keywords

  • nullptr is the replacement for NULL macro in C. Using nullptr allows any pointer type but not integer. When NULL is used instead, 0 can add uncertainty of intention in code.

      const uint32_t *ptr = nullptr;
    
  • constexpr is constant expression. The benefit of using constexpr increases the runtime performance because the expression is evaluated at compile time. It is useful for converting the unit from one system to another. This keyword is supported since C++11.

      #include <iostream>
    
      constexpr float fahrenheit_to_Celsius(float fahrenheit)
      {
          return ((fahrenheit - 32.0) * 5.0 / 9.0);
      }
    
      int main()
      {
          float x = fahrenheit_to_Celsius(10);
          std::cout << x;
          return 0;
      }
    
  • enum class is scoped enumeration. The regular enum type used to store enum values. This keyword is also supported since C++11.

      #include <iostream>
      using namespace std;
    
      int main()
      {
    
          enum class TrafficLightColor { Red, Green, Yellow };
    
          // Init
          TrafficLightColor x = TrafficLightColor::Green;
    
          // Type-safe
          if (x == TrafficLightColor::Red)
              cout << "It's Red\n";
          else
              cout << "It's not Red\n";
    
          return 0;
      }
    
  • using can replace typedef in C. The code would be more readable. Also, it can define function pointers.

      #include <iostream>
      using namespace std;
    
      uint32_t square(uint32_t x) { return x*x; } 
    
      int main()
      {
          //Simplify typedef
          using UL = unsigned long;   //typedef unsigned long UL;
          UL big_number = 12740917590135790238U;
    
          using func = uint32_t(*)(uint32_t); //uint32_t (*func)(uint32_t);
          func fptr = &square;                //func = square;
    
          cout << big_number << endl;
          cout << fptr(10) << endl;
      }
    
  • binary literals and digit separator are supported from C++14.

      uint8_t write_register = 0b10010000;    //binary literals
    
      uint16_t var = 0b1010'0000'1100'0010;    //digit separator
    
  • auto provides stronger compile-time checks to reduce bugs. With auto keyword, compiler error if variable is not initialized. Also, the compiler works out type from initialization.

      #include <iostream>
    
      using namespace std;
    
      uint32_t square(uint8_t x) { return x*x; }
      uint16_t add(uint16_t x, uint16_t y) { return x+y; }
    
      int main( )
      {
          for(auto i = 0U; i < 5U; i++)
          {
              cout << i << endl;
          }
    
          auto num1 = square(10);
          auto num2 = add(2, 4);
    
          cout << num1 << endl;
          cout << num2 << endl;
      }
    

Did you find this article valuable?

Support Hyunwoo Choi by becoming a sponsor. Any amount is appreciated!