繁体   English   中英

如何检查模板类型参数是字符类型还是字符串类型?

[英]How can I check if a template type parameter is a character type or a string type?

我正在尝试编写能够区分字符类型( charwchar_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_typeis_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>truedetect_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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM