CodeNebula
C++17stladvanced

std::bool_constant

C++17 · Practical Modern · Compiler flag: -std=c++17

Explanation

An alias template for `std::integral_constant<bool, B>`, providing a shorter way to define compile-time boolean constants. `std::true_type` and `std::false_type` are specializations of it.

Real-World Scenario

Define custom type traits that produce clean true/false compile-time values for a serialization framework.

Quick Snippet

snippet.cpp
#include <type_traits>

template<typename T>
using is_small = std::bool_constant<(sizeof(T) <= sizeof(void*))>;

static_assert(is_small<int>::value);
static_assert(!is_small<std::array<int, 100>>::value);

Full Example

bool_constant.cpp
// CodeNebula - C++17 Example: std::bool_constant
// Compile: g++ -std=c++17 -Wall -Wextra -o example bool_constant.cpp

// Demonstrates std::bool_constant, a C++17 alias for
// std::integral_constant<bool, B>. It simplifies writing custom type
// traits and serves as the base for std::true_type and std::false_type.

#include <iostream>
#include <type_traits>
#include <string>
#include <vector>

// ------------------------------------------------------------------
// Custom traits using bool_constant
// ------------------------------------------------------------------

// Check if a type is a pointer-to-const
template <typename T>
struct is_pointer_to_const : std::bool_constant<
    std::is_pointer_v<T> && std::is_const_v<std::remove_pointer_t<T>>
> {};

// Check if a type is small (fits in a register)
template <typename T>
struct is_small : std::bool_constant<(sizeof(T) <= sizeof(void*))> {};

// Check if a type is a signed integer type
template <typename T>
struct is_signed_integer : std::bool_constant<
    std::is_integral_v<T> && std::is_signed_v<T> && !std::is_same_v<T, bool>
> {};

// Conditional trait composition
template <typename T>
struct is_numeric_and_small : std::bool_constant<
    std::is_arithmetic_v<T> && is_small<T>::value
> {};

int main()
{
    // ------------------------------------------------------------------
    // 1. bool_constant basics
    // ------------------------------------------------------------------
    using always_true  = std::bool_constant<true>;
    using always_false = std::bool_constant<false>;

    std::cout << "=== bool_constant Basics ===" << std::endl;
    std::cout << "  bool_constant<true>  = " << always_true::value << std::endl;
    std::cout << "  bool_constant<false> = " << always_false::value << std::endl;
    std::cout << "  Same as true_type?   : "
              << std::is_same_v<always_true, std::true_type> << std::endl;

    // ------------------------------------------------------------------
    // 2. is_pointer_to_const
    // ------------------------------------------------------------------
    std::cout << "\n=== is_pointer_to_const ===" << std::endl;
    std::cout << "  const int*   : " << is_pointer_to_const<const int*>::value << std::endl;
    std::cout << "  int*         : " << is_pointer_to_const<int*>::value << std::endl;
    std::cout << "  int* const   : " << is_pointer_to_const<int* const>::value << std::endl;

    // ------------------------------------------------------------------
    // 3. is_small
    // ------------------------------------------------------------------
    std::cout << "\n=== is_small (<=8 bytes) ===" << std::endl;
    std::cout << "  int          : " << is_small<int>::value << std::endl;
    std::cout << "  double       : " << is_small<double>::value << std::endl;
    std::cout << "  std::string  : " << is_small<std::string>::value << std::endl;

    // ------------------------------------------------------------------
    // 4. is_signed_integer
    // ------------------------------------------------------------------
    std::cout << "\n=== is_signed_integer ===" << std::endl;
    std::cout << "  int          : " << is_signed_integer<int>::value << std::endl;
    std::cout << "  unsigned     : " << is_signed_integer<unsigned>::value << std::endl;
    std::cout << "  bool         : " << is_signed_integer<bool>::value << std::endl;
    std::cout << "  double       : " << is_signed_integer<double>::value << std::endl;

    // ------------------------------------------------------------------
    // 5. Composed trait
    // ------------------------------------------------------------------
    std::cout << "\n=== is_numeric_and_small ===" << std::endl;
    std::cout << "  int          : " << is_numeric_and_small<int>::value << std::endl;
    std::cout << "  float        : " << is_numeric_and_small<float>::value << std::endl;
    std::cout << "  long double  : " << is_numeric_and_small<long double>::value << std::endl;
    std::cout << "  std::string  : " << is_numeric_and_small<std::string>::value << std::endl;

    return 0;
}

/*
Expected output:

=== bool_constant Basics ===
  bool_constant<true>  = 1
  bool_constant<false> = 0
  Same as true_type?   : 1

=== is_pointer_to_const ===
  const int*   : 1
  int*         : 0
  int* const   : 0

=== is_small (<=8 bytes) ===
  int          : 1
  double       : 1
  std::string  : 0

=== is_signed_integer ===
  int          : 1
  unsigned     : 0
  bool         : 0
  double       : 0

=== is_numeric_and_small ===
  int          : 1
  float        : 1
  long double  : 0
  std::string  : 0
*/
Run command
g++ -std=c++17 -Wall -Wextra -o example bool_constant.cpp