用户定义的类型特征会给出意外的 false 类型



>打印包含类型信息的字符串:

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]> << "nn";
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)> << "nn";
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
  • 当它们与string3char [6]具有相同的类型时,为什么is_string_v<decltype(some string literal)>false在作为模板参数传递时具有true值?
  • 我的拆卸功能有问题吗?(因为我的实现不包括引用)

这对我来说很有用:

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添加了一个额外的参考。取自这个答案:

decltype(e)表示的类型定义如下:

  • 如果e是无括号的 ID 表达式或无括号的类成员访问,则decltype(e)是由e命名的实体的类型。如果没有这样的实体,或者e命名一组重载函数,则程序格式不正确;

  • 否则,如果e是x值,则decltype(e)T&&,其中Te的类型;

  • 否则,如果e是左值,则decltype(e)T&,其中Te的类型;

  • 否则,decltype(e)e的类型。

§7.1.6.2 [dcl.type.simple]

字符串文字是左值,因此它添加了引用。

问题是 c 样式的字符串文字,例如"Hello"是一个表达式,然后decltype产生 type 作为T&,即const char (&) [6]"Hello".(请注意,对于无括号的 id-表达式或无括号的类成员访问表达式以及任何其他表达式,decltype以两种不同的方式工作。

您可以将专业化添加为

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等。

最新更新