Quick Links:

bal | bbl | bdl | bsl

Namespaces

Component bsls_nameof
[Package bsls]

Provide a NameOf type for displaying template type at run-time. More...

Namespaces

namespace  bsls

Detailed Description

Outline
Purpose:
Provide a NameOf type for displaying template type at run-time.
Classes:
bsls::NameOf template class to return name of template parameter
FREE FUNCTIONS:

bsls::nameOfType(const TYPE&): template function to return name of TYPE

Description:
This component provides a template class, bsls::NameOf<TYPE>, which can implicitly cast to a const char * which will point to a description of TYPE.
Usage:
This section illustrates intended usage of this component.
Example 1:
First, your test driver must have the following using statements so that the template class NameOf and the template function nameOfType can be referred to concisely, without having to qualify them with namespaces on each call. Note that if you've already said using namespace BloombergLP you don't have to give the BloombergLP:: qualifiers here:
  using BloombergLP::bsls::NameOf;
  using BloombergLP::bsls::nameOfType;
Next, we define some types in the unnamed namespace:
  namespace {

  struct MyType {
      int  d_i;
      char d_c;
  };

  union MyUnion {
      int  d_i;
      char d_buffer[100];
  };

  }  // close unnamed namespace
Next, we see that the NameOf template class, when created with a type, can be implicitly cast to a const char * which points to a description of the type.
  assert(!std::strcmp("double", NameOf<double>()));
  assert(!std::strcmp("int",    NameOf<int>()));
Then, we see that when NameOf is passed a typedef or template parameter, it resolves it to the original type:
  typedef int Woof;

  assert(!std::strcmp("int",    NameOf<Woof>()));
Next, we introduce the nameOfType template function, which takes as any variable as an argument, and returns a const char * pointing to a description of the type of the variable.
  int ii = 2;

  assert(!std::strcmp("int",    nameOfType(ii)));
Then, we see that NameOf and nameOfType will strip BloombergLP:: namespace qualifiers, as well as anonymous namespace qualifiers.
  typedef BloombergLP::bsls::Stopwatch SW;

  const SW      sw;
  const MyType  mt = { 2, 'a' };
  MyUnion       mu;
  mu.d_i = 7;

  assert(!std::strcmp("bsls::Stopwatch", NameOf<SW>()));
  assert(!std::strcmp("bsls::Stopwatch",
                                    NameOf<BloombergLP::bsls::Stopwatch>()));
  assert(!std::strcmp("bsls::Stopwatch", nameOfType(sw)));

  assert(!std::strcmp("MyType",          NameOf<MyType>()));
  assert(!std::strcmp("MyType",          nameOfType(mt)));

  assert(!std::strcmp("MyUnion",         NameOf<MyUnion>()));
  assert(!std::strcmp("MyUnion",         nameOfType(mu)));
There is a problem with template code not knowing how to implicitly cast the NameOf type to const char * for initializing or comparing with std::strings. To facilitate, NameOf provides a const char * name accessor, to avoid the user having to do a more verbose static cast.
  const std::string swName = "bsls::Stopwatch";
  assert(swName == static_cast<const char *>(NameOf<SW>()));
  assert(swName == NameOf<SW>().name());

  const std::string swNameB = NameOf<SW>().name();
  assert(swNameB == swName);

  printf("NameOf<SW>() = \"%s\"\n", NameOf<SW>().name());
  printf("NameOfType(4 + 3) = \"%s\"\n", nameOfType(4 + 3));
Note that nameOfType naturally returns a const char * and needs no help casting. Note also that bsls::debugprint is able to figure out how to cast NameOf directly to const char * with no problems, as can iostreams, so there is no problem with putting a NameOf in a LOOP_ASSERT or ASSERTV. It is anticipated that displaying by the BDE ASSERTV, LOOP_ASSERT, and 'P macros will be the primary use of this component.
  printf("NameOf<double>() = ");
  BloombergLP::bsls::debugprint(NameOf<double>());
  printf("\n");

  typedef double DTYPE;
  DTYPE x = 7.3;

  LOOP_ASSERT(NameOf<DTYPE>(), x > 7);

  std::string myStr;              // Assign, not init, of string doesn't need
  myStr = NameOf<DTYPE>();        // '.name()'.
  assert("double" == myStr);
Which produces:
  NameOf<SW>() = "bsls::Stopwatch"
Finally, we see that NameOf and nameOfType will simplify std::basic_string<...> declarations to std::string.
  const std::string s = "std::string";

  assert(s == NameOf<std::basic_string<char> >().name());
  assert(s == NameOf<std::string>().name());
  assert(s == nameOfType(s));

  typedef NameOf<std::string> Nos;

  const std::string s2 = "bsls::NameOf<std::string>";

  assert(s2 == NameOf<NameOf<std::basic_string<char> > >().name());
  assert(s2 == NameOf<NameOf<std::string> >().name());
  assert(s2 == NameOf<Nos>().name());
  assert(s2 == nameOfType(Nos()));