用户定义的类型特征给出了意外的错误类型
User defined type trait gives an unexpected false type
打印包含类型信息的字符串:
std::string demangle(const char* mangled_name) {
size_t len = 0;
int status = 0;
std::unique_ptr<char, decltype(&std::free)> pointer (
__cxxabiv1::__cxa_demangle(mangled_name, nullptr, &len, &status),
&std::free);
return pointer.get();
}
template <typename T>
std::string type_of(const T& arg) {
return demangle(typeid(arg).name());
}
我的自定义 is_string
类型特征:
template <typename T> struct is_string : std::false_type {};
template <> struct is_string<char*> : std::true_type {};
template <> struct is_string<char[]> : std::true_type {};
template <size_t N> struct is_string<char[N]> : std::true_type {};
template <> struct is_string<const char*> : std::true_type {};
template <> struct is_string<const char[]> : std::true_type {};
template <size_t N> struct is_string<const char[N]> : std::true_type {};
// Helper variable:
template <typename T>
constexpr bool is_string_v = is_string<T>::value;
申请:
std::cout << std::boolalpha;
std::cout << "Testing: " << '\n'
<< "char* = " << is_string_v<char*> << '\n'
<< "char[] = " << is_string_v<char[]> << '\n'
<< "char[10] = " << is_string_v<char[10]> << '\n'
<< "char[15] = " << is_string_v<char[15]> << '\n'
<< "const char* = " << is_string_v<const char*> << '\n'
<< "const char[] = " << is_string_v<const char[]> << '\n'
<< "const char[3] = " << is_string_v<const char[3]> << '\n'
<< "const char[6] = " << is_string_v<const char[6]> << "\n\n";
const char* string1 = "Hello";
const char string2[] = "Hello";
char string3[] = "Hello";
auto string4 = "Hello";
std::cout << "Testing with decltype(variable): " << '\n'
<< type_of(string1) << " = " << is_string_v<decltype(string1)> << '\n'
<< type_of(string2) << " = " << is_string_v<decltype(string2)> << '\n'
<< type_of(string3) << " = " << is_string_v<decltype(string3)> << '\n'
<< type_of(string4) << " = " << is_string_v<decltype(string4)> << "\n\n";
std::cout << "Testing with string literal: " << '\n'
<< type_of("Hello") << " = " << is_string_v<decltype("Hello")> << '\n';
输出:
Testing:
char* = true
char[] = true
char[10] = true
char[15] = true
const char* = true
const char[] = true
const char[3] = true
const char[6] = true
Testing with decltype(variable):
char const* = true
char [6] = true
char [6] = true
char const* = true
Testing with string literal:
char [6] = false
- 为什么
is_string_v<decltype(some string literal)>
false
与 string3
或 char [6]
具有相同的类型,当它作为模板参数传递时具有 true
值?
- 是不是我的demangling功能有问题? (因为我的实现不包含参考)
这对我有用:
int main()
{
std::cout << is_string_v<char const[sizeof "Hello"]> << '\n';
std::cout << is_string_v<std::remove_reference_t<decltype("Hello")>> << '\n';
}
输出:
1
1
看起来 decltype
添加了额外的参考。摘自 this answer:
The type denoted by decltype(e)
is defined as follows:
if e
is an unparenthesized id-expression or an unparenthesized class member access, decltype(e)
is the type of the entity named by e
. If there is no such entity, or if e
names a set of overloaded functions, the program is ill-formed;
otherwise, if e
is an xvalue, decltype(e)
is T&&
, where T
is the type of e
;
otherwise, if e
is an lvalue, decltype(e)
is T&
, where T
is the type of e
;
otherwise, decltype(e)
is the type of e
.
§7.1.6.2 [dcl.type.simple]
和string literals are lvalues,所以它添加了一个引用。
问题是像 "Hello"
这样的 c 风格字符串文字是一个表达式,然后 decltype
产生类型为 T&
,即 const char (&) [6]
for "Hello"
. (请注意,decltype
以两种不同的方式用于未加括号的 id 表达式或未加括号的 class 成员访问表达式,以及任何其他表达式。)
您可以将专业化添加为
template <size_t N> struct is_string<const char(&)[N]> : std::true_type {};
添加
template<class T> struct is_string<T&>:is_string<T>{};
template<class T> struct is_string<T&&>:is_string<T>{};
template<class T> struct is_string<T const>:is_string<T>{};
template<class T> struct is_string<T volatile>:is_string<T>{};
template<class T> struct is_string<T const volatile>:is_string<T>{};
并删除 const char[]
和 const char[N]
专业。
您可能还想支持 u8
字符串和 wchar_t 等
打印包含类型信息的字符串:
std::string demangle(const char* mangled_name) {
size_t len = 0;
int status = 0;
std::unique_ptr<char, decltype(&std::free)> pointer (
__cxxabiv1::__cxa_demangle(mangled_name, nullptr, &len, &status),
&std::free);
return pointer.get();
}
template <typename T>
std::string type_of(const T& arg) {
return demangle(typeid(arg).name());
}
我的自定义 is_string
类型特征:
template <typename T> struct is_string : std::false_type {};
template <> struct is_string<char*> : std::true_type {};
template <> struct is_string<char[]> : std::true_type {};
template <size_t N> struct is_string<char[N]> : std::true_type {};
template <> struct is_string<const char*> : std::true_type {};
template <> struct is_string<const char[]> : std::true_type {};
template <size_t N> struct is_string<const char[N]> : std::true_type {};
// Helper variable:
template <typename T>
constexpr bool is_string_v = is_string<T>::value;
申请:
std::cout << std::boolalpha;
std::cout << "Testing: " << '\n'
<< "char* = " << is_string_v<char*> << '\n'
<< "char[] = " << is_string_v<char[]> << '\n'
<< "char[10] = " << is_string_v<char[10]> << '\n'
<< "char[15] = " << is_string_v<char[15]> << '\n'
<< "const char* = " << is_string_v<const char*> << '\n'
<< "const char[] = " << is_string_v<const char[]> << '\n'
<< "const char[3] = " << is_string_v<const char[3]> << '\n'
<< "const char[6] = " << is_string_v<const char[6]> << "\n\n";
const char* string1 = "Hello";
const char string2[] = "Hello";
char string3[] = "Hello";
auto string4 = "Hello";
std::cout << "Testing with decltype(variable): " << '\n'
<< type_of(string1) << " = " << is_string_v<decltype(string1)> << '\n'
<< type_of(string2) << " = " << is_string_v<decltype(string2)> << '\n'
<< type_of(string3) << " = " << is_string_v<decltype(string3)> << '\n'
<< type_of(string4) << " = " << is_string_v<decltype(string4)> << "\n\n";
std::cout << "Testing with string literal: " << '\n'
<< type_of("Hello") << " = " << is_string_v<decltype("Hello")> << '\n';
输出:
Testing:
char* = true
char[] = true
char[10] = true
char[15] = true
const char* = true
const char[] = true
const char[3] = true
const char[6] = true
Testing with decltype(variable):
char const* = true
char [6] = true
char [6] = true
char const* = true
Testing with string literal:
char [6] = false
- 为什么
is_string_v<decltype(some string literal)>
false
与string3
或char [6]
具有相同的类型,当它作为模板参数传递时具有true
值? - 是不是我的demangling功能有问题? (因为我的实现不包含参考)
这对我有用:
int main()
{
std::cout << is_string_v<char const[sizeof "Hello"]> << '\n';
std::cout << is_string_v<std::remove_reference_t<decltype("Hello")>> << '\n';
}
输出:
1
1
看起来 decltype
添加了额外的参考。摘自 this answer:
The type denoted by
decltype(e)
is defined as follows:
if
e
is an unparenthesized id-expression or an unparenthesized class member access,decltype(e)
is the type of the entity named bye
. If there is no such entity, or ife
names a set of overloaded functions, the program is ill-formed;otherwise, if
e
is an xvalue,decltype(e)
isT&&
, whereT
is the type ofe
;otherwise, if
e
is an lvalue,decltype(e)
isT&
, whereT
is the type ofe
;otherwise,
decltype(e)
is the type ofe
.§7.1.6.2 [dcl.type.simple]
和string literals are lvalues,所以它添加了一个引用。
问题是像 "Hello"
这样的 c 风格字符串文字是一个表达式,然后 decltype
产生类型为 T&
,即 const char (&) [6]
for "Hello"
. (请注意,decltype
以两种不同的方式用于未加括号的 id 表达式或未加括号的 class 成员访问表达式,以及任何其他表达式。)
您可以将专业化添加为
template <size_t N> struct is_string<const char(&)[N]> : std::true_type {};
添加
template<class T> struct is_string<T&>:is_string<T>{};
template<class T> struct is_string<T&&>:is_string<T>{};
template<class T> struct is_string<T const>:is_string<T>{};
template<class T> struct is_string<T volatile>:is_string<T>{};
template<class T> struct is_string<T const volatile>:is_string<T>{};
并删除 const char[]
和 const char[N]
专业。
您可能还想支持 u8
字符串和 wchar_t 等