title: How can I check if a template type parameter is a character type or a string type?
body: <p>I am trying to write code that will be able to distinguish between character types (<code>char</code>, <code>wchar_t</code>, etc.), string types (std::string, std::wstring, etc.), and numeric types, so I can enclose characters in single-quotes and strings in double-quotes. The idea is to treat values differently depending on how they are output. Characters and strings are fundamentally different from numeric values, because they display according to an encoding representation of their contents (i.e., ASCII, Unicode, UTF, etc.), rather than as numeric values.</p>
  
  <p><em>(Note: this code is extracted from a much larger and more complicated program)</em></p>
  
  <p>Here's my code, compiled with</p>
  
  <pre><code>g++ -std=c++14 testchar.cpp -o testchar
  </code></pre>
  
  <p>which works under Linux Mint 18.3 (Sylvia) compiled with g++ v5.4.0</p>
  
  <pre><code>#include &lt;iostream&gt;
  #include &lt;locale&gt;
  #include &lt;codecvt&gt;
  #include &lt;string&gt;
  #include &lt;type_traits&gt;
  
  using std::cout;
  using std::is_same;
  using std::string;
  using std::u16string;
  using std::u32string;
  using std::wstring;
  
  #define is_string_type(T)  ( is_same&lt;T,string&gt;::value    || is_same&lt;T,wstring&gt;::value   || \
                               is_same&lt;T,u16string&gt;::value || is_same&lt;T,u32string&gt;::value )
  #define is_char_type(T)    ( is_same&lt;T,char&gt;::value      || is_same&lt;T,wchar_t&gt;::value   || \
                               is_same&lt;T,char16_t&gt;::value  || is_same&lt;T,char32_t&gt;::value  )
  #define is_numeric_type(T) ( !is_char_type(T) &amp;&amp; std::is_arithmetic&lt;T&gt;::value )
  
  template &lt;typename T&gt;
  typename std::enable_if&lt;is_string_type(T),void&gt;::type
  output_value( const string&amp; name, const T&amp; strval ) {
      cout &lt;&lt; "String " &lt;&lt; name &lt;&lt; " is \"" &lt;&lt; strval &lt;&lt; "\";\n";
  }
  template &lt;typename T&gt;
  typename std::enable_if&lt;is_char_type(T),void&gt;::type
  output_value( const string&amp; name, const T&amp; chrval ) {
      cout &lt;&lt; "Character " &lt;&lt; name &lt;&lt; " is '" &lt;&lt; chrval &lt;&lt; "';\n";
  }
  template &lt;typename T&gt;
  typename std::enable_if&lt;is_numeric_type(T),void&gt;::type
  output_value( const string&amp; name, const T&amp; val ) {
      cout &lt;&lt; "Numeric " &lt;&lt; name &lt;&lt; " is " &lt;&lt; val &lt;&lt; ";\n";
  }
  
  int main(void)
  {
      string    name;
      short     sval = 4321;
      int       ival = 123;
      long      lval = 1234567890L;
      char      cval = 'W';
      string    Sval = "string";
  
      name = "sval";
      output_value( name, sval );
      name = "ival";
      output_value( name, ival );
      name = "lval";
      output_value( name, lval );
      name = "cval";
      output_value( name, cval );
      name = "strval";
      output_value( name, Sval );
  
      return 0;
  }
  </code></pre>
  
  <p>But my macros, 'is_char_type' and 'is_string_type' are ugly and not very robust. And they are macros... yuck! I did try using <code>std::is_base_of&lt;std::basic_string,T&gt;::value</code> for `is_string_type', but the compiler threw an error:</p>
  
  <pre><code>testchar.cpp:17:65: error: type/value mismatch at argument 1 in template parameter list for ‘template&lt;class, class&gt; struct std::is_base_of’
  </code></pre>
  
  <p>If anyone knows a better way to do this please let me know!  I'm kind of surprised these (<code>is_character_type</code> and <code>is_string_type</code>) don't already exist in <code>type_traits</code>... or perhaps they do, but are cleverly disguised?</p>