I am trying to write code that will be able to distinguish between character types (char
, wchar_t
, 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.
(Note: this code is extracted from a much larger and more complicated program)
Here's my code, compiled with
g++ -std=c++14 testchar.cpp -o testchar
which works under Linux Mint 18.3 (Sylvia) compiled with g++ v5.4.0
#include <iostream>
#include <locale>
#include <codecvt>
#include <string>
#include <type_traits>
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<T,string>::value || is_same<T,wstring>::value || \
is_same<T,u16string>::value || is_same<T,u32string>::value )
#define is_char_type(T) ( is_same<T,char>::value || is_same<T,wchar_t>::value || \
is_same<T,char16_t>::value || is_same<T,char32_t>::value )
#define is_numeric_type(T) ( !is_char_type(T) && std::is_arithmetic<T>::value )
template <typename T>
typename std::enable_if<is_string_type(T),void>::type
output_value( const string& name, const T& strval ) {
cout << "String " << name << " is \"" << strval << "\";\n";
}
template <typename T>
typename std::enable_if<is_char_type(T),void>::type
output_value( const string& name, const T& chrval ) {
cout << "Character " << name << " is '" << chrval << "';\n";
}
template <typename T>
typename std::enable_if<is_numeric_type(T),void>::type
output_value( const string& name, const T& val ) {
cout << "Numeric " << name << " is " << val << ";\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;
}
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 std::is_base_of<std::basic_string,T>::value
for `is_string_type', but the compiler threw an error:
testchar.cpp:17:65: error: type/value mismatch at argument 1 in template parameter list for ‘template<class, class> struct std::is_base_of’
If anyone knows a better way to do this please let me know! I'm kind of surprised these (is_character_type
and is_string_type
) don't already exist in type_traits
... or perhaps they do, but are cleverly disguised?