Quick Links:

bal | bbl | bdl | bsl

Classes | Typedefs | Functions | Variables

Component bslmf_isempty
[Package bslmf]

Provide a compile-time check for detecting an empty class type. More...

Classes

struct  bsl::Is_Empty_Class_Imp< t_TYPE, IS_CLASS >
struct  bsl::Is_Empty_Class_Imp< t_TYPE, true >
struct  bsl::Is_Empty_Imp< t_TYPE, class >
struct  bsl::Is_Empty_Imp< t_TYPE, BSLMF_VOIDTYPE(int t_TYPE::*)>
struct  bsl::is_empty< t_TYPE >
struct  bsl::is_empty< const t_TYPE >
struct  bsl::is_empty< volatile t_TYPE >
struct  bsl::is_empty< const volatile t_TYPE >

Typedefs

typedef integral_constant
< bool, sizeof(Derived)==sizeof(int)> 
bsl::Is_Empty_Class_Imp< t_TYPE, true >::type

Functions

 bsl::Is_Empty_Class_Imp< t_TYPE, true >::Derived::Derived (const Derived &)
 bsl::Is_Empty_Class_Imp< t_TYPE, true >::Derived::~Derived ()

Variables

int bsl::Is_Empty_Class_Imp< t_TYPE, true >::Derived::d_data

Detailed Description

Outline
Purpose:
Provide a compile-time check for detecting an empty class type.
Classes:
bsl::is_empty standard meta-function for detecting empty classes
bsl::is_empty_v the result value of the bsl::is_empty meta-function
See also:
bslmf_isclass.h
Description:
This component defines a meta-function, bsl::is_empty and a template variable bsl::is_empty_v, that represents the result value of the bsl::is_empty meta-function, which may be used to determine whether a type is a class or struct with no non-static data members other than bit-fields of length 0, no virtual member functions, no virtual base classes, and no base class B for which is_empty<B>value is false. This meta-function conforms to the definition of the C++11 standard is_empty meta-function in section [meta.unary.prop].
An empty class type type is usually stateless and, can be "stored" in a zero-length memory region. (Hypothetically, an empty object can hold state by means a global address-to-state map, but such a design is rare and is discouraged.) When a class inherits from an empty type, the compiler is expected to optimize away the storage requirements of the empty base class. This optimization is known as the "Empty Base Optimization" or "EBO".
Note that the template variable is_empty_v is defined in the C++17 standard as an inline variable. If the current compiler supports the inline variable C++17 compiler feature, bsl::is_empty_v is defined as an inline constexpr bool variable. Otherwise, if the compiler supports the variable templates C++14 compiler feature, bsl::is_empty_v is defined as a non-inline constexpr bool variable. See BSLS_COMPILERFEATURES_SUPPORT_INLINE_VARIABLES and BSLS_COMPILERFEATURES_SUPPORT_VARIABLE_TEMPLATES macros in bsls_compilerfeatures component for details.
Usage:
In this section we show intended use of this component.
Example 1: Compute Storage Requirements for a Type:
Suppose we wish to create a generic function that will allocate a record comprising a value of specified t_TYPE and a description in the form of a null-terminated character string. First, we declare the function prototype:
  template <class t_TYPE>
  void *makeRecord(const t_TYPE& value, const char* description);
Next, we implement the function so that the copy of value takes up no space if t_TYPE is an empty class. We manage this by computing a zero storage requirement if is_empty<t_TYPE>value is true:
  #include <cstring>
  #include <new>

  template <class t_TYPE>
  void *makeRecord(const t_TYPE& value, const char* description)
  {
      // 'ValueSize' is computed at compile time.
      static const std::size_t ValueSize = bsl::is_empty<t_TYPE>::value ?
          0 : sizeof(t_TYPE);

      // Allocate memory for value and description
      const std::size_t MemSize = ValueSize + std::strlen(description) + 1;
      void *mem = ::operator new(MemSize);

      // Construct copy of value at front of allocated memory
      ::new(mem) t_TYPE(value);

      // Copy description into space following value.
      std::strcpy(static_cast<char*>(mem) + ValueSize, description);

      return mem;
  }
Finally, we use makeRecord with both an empty and non-empty value type:
  struct EmptyMarker { };

  int main()
  {
      void *record1 = makeRecord(9999, "four nines");
      // Value takes 'sizeof(int)' bytes at front of record.
      assert(9999 == *static_cast<int*>(record1));
      assert(0 == std::strcmp(static_cast<char*>(record1) + sizeof(int),
                              "four nines"));

      void *record2 = makeRecord(EmptyMarker(), "Empty");
      // Value takes no space at front of record.
      assert(0 == std::strcmp(static_cast<char*>(record2), "Empty"));

      ::operator delete(record1);
      ::operator delete(record2);

      return 0;
  }

Typedef Documentation

template<class t_TYPE >
typedef integral_constant<bool, sizeof(Derived) == sizeof(int)> bsl::Is_Empty_Class_Imp< t_TYPE, true >::type [inherited]

true_type if (the template parameter) t_TYPE is an empty class, and false_type otherwise.


Function Documentation

template<class t_TYPE >
bsl::Is_Empty_Class_Imp< t_TYPE, true >::Derived::Derived ( const Derived &   )  [inherited]

Declared but not defined

template<class t_TYPE >
bsl::Is_Empty_Class_Imp< t_TYPE, true >::Derived::~Derived (  )  [inherited]

Variable Documentation

template<class t_TYPE >
int bsl::Is_Empty_Class_Imp< t_TYPE, true >::Derived::d_data [inherited]

Derived is not empty