[英]How can I check if a template type parameter is a character type or a string type?
我正在尝试编写能够区分字符类型( char
, wchar_t
等),字符串类型(std :: string,std :: wstring等)和数字类型的代码,因此我可以将字符括起来单引号和双引号的字符串。 想法是根据值的输出方式来区别对待值。 字符和字符串从根本上不同于数字值,因为它们根据其内容的编码表示(即ASCII,Unicode,UTF等)显示,而不是作为数字值显示。
(注意:此代码是从更大,更复杂的程序中提取的)
这是我的代码,使用
g++ -std=c++14 testchar.cpp -o testchar
它在使用g ++ v5.4.0编译的Linux Mint 18.3(Sylvia)下工作
#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;
}
但是我的宏“ is_char_type”和“ is_string_type”很丑陋,而且不够健壮。 而且它们是宏......! 我确实尝试使用std::is_base_of<std::basic_string,T>::value
is_string_type的std::is_base_of<std::basic_string,T>::value
,但是编译器抛出错误:
testchar.cpp:17:65: error: type/value mismatch at argument 1 in template parameter list for ‘template<class, class> struct std::is_base_of’
如果有人知道更好的方法,请告诉我! 这些类型( is_character_type
和is_string_type
)尚不存在于type_traits
……或者也许它们确实存在,但是我被巧妙地掩盖了,我对此感到is_character_type
惊讶。
template<class T>struct tag_t{};
template<class T>constexpr tag_t<T> tag{};
namespace detect_string {
template<class T, class...Ts>
constexpr bool is_stringlike(tag_t<T>, Ts&&...){ return false; }
template<class T, class A>
constexpr bool is_stringlike( tag_t<std::basic_string<T,A>> ){ return true; }
template<class T>
constexpr bool detect=is_stringlike(tag<T>); // enable ADL extension
}
namespace detect_character {
template<class T, class...Ts>
constexpr bool is_charlike(tag_t<T>, Ts&&...){ return false; }
constexpr bool is_charlike( tag_t<char> ){ return true; }
constexpr bool is_charlike( tag_t<wchar_t> ){ return true; }
// ETC
template<class T>
constexpr bool detect=is_charlike(tag<T>); // enable ADL extension
}
现在detect_character::detect<char>
为true
, detect_string::detect<std::wstring>
。
如果只希望将charlikes字符串作为字符串,请将其添加到is_stringlike
重载中。
您可以通过在类型X的名称空间中定义is_stringlike(tag_t<X>)
重载来扩展其中的任何一个,并将自动找到它。 或在detect_stringlike
这样做。 您可能不会以这种方式向std
添加重载,因此请在detect_stringlike
命名空间中进行detect_stringlike
。
还有其他解决方案,但这是避免单个中央列表的脆弱性的唯一解决方案。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.