【问题标题】:typeid("") != typeid(const char*)typeid("") != typeid(const char*)
【发布时间】:2019-06-13 01:35:10
【问题描述】:

我正在制作一个 C++ 库,它严重依赖于 RTTI(可自定义桥接至另一种语言)并且对字符串文字类型非常困惑。

这是我为说明问题所做的一个简单测试:

std::cout << typeid(const char*).name() << std::endl; // PKc
std::cout << std::any("").type().name() << std::endl; // PKc
std::cout << typeid("").name() << std::endl;          // A1_c

对我来说,前两个打印出const char* 的类型,但最后一个是数组。

为什么std::any("").type()typeid("") 的结果不同?有没有办法获得第一个行为,即使字符串文字的结果一致(我使用类型标识来调用不同的类型处理程序)?

P.S.:测试是在 Ubuntu 19.04 上使用 Clang 版本 8.0.0-3 (tags/RELEASE_800/final) 完成的。

【问题讨论】:

  • "" 不是 const char*,因此它们没有匹配的类型。 ""const char[],一个 const char 数组。
  • @Eljay 问题不在于它们是否是不同的类型。这是问题的前提。问题是为什么std::any("").type() 不是数组(A1_c)。
  • 补充@Eljay 的评论:第二行(std::any)是一个指针,因为 char 数组在传递给构造函数时会衰减为指针。
  • @Timo 是通过引用传递的,所以传递时不会衰减。

标签: c++ c++17 rtti string-literals


【解决方案1】:

正如其他人所提到的,字符串文字 "" 的类型是 const char[1],如 What is the datatype of string literal in C++? 所解释的那样。

std::any("") 中存储的类型是const char*,因为您使用的是以下构造函数(http://www.eel.is/c++draft/any.cons#8):

// Effects: Constructs an object of type any that contains an object of 
// type std::decay_t<T> direct-initialized with std::forward<T>(value).
template< class T>
any( T&& value );

在这种情况下,Tconst char(&amp;)[1](字符串文字 "" 的类型),因此 std::decay_t&lt;const char(&amp;)[1]&gt; 将给您 const char*,这就是为什么 std::any("").type()typeid()const char* 的类型 ID。

【讨论】:

  • 所以我想要在typeid之前申请std::decay
  • @val 我真的不知道你想做什么(从你的问题中不清楚),但如果你从T 类型的对象创建std::decay_t&lt;T&gt; 类型的对象,这应该给你这种行为,类似于std::any行为。
【解决方案2】:

为什么std::any("").type()typeid("") 的结果不同?

根据以下reference

template< class ValueType >
any( ValueType&& value );

4) 构造一个具有初始内容的对象 std::decay_t&lt;ValueType&gt; 类型的对象,直接从 std::forward&lt;ValueType&gt;(value) 初始化。

std::decay_t&lt;const char[1]&gt;const char*


这是 FrankHB1989 在isocpp.org forum 上的引述,我认为这与理解std::any 有关,在这个问题的背景下:

[std::any] 甚至不适用于“任何对象”。正如我之前所说,我希望“any”这个词是“any first-class object type”(即 cv-unqualified 非数组对象类型)的缩写,但 std::any 在值类型上对 CopyConstructible 进行了额外改进, 所以它实际上是针对“任何可复制的 cv-unqualified 非数组对象类型”。

这样

有没有办法获得第一个行为,即使字符串文字的结果一致(我使用类型标识来调用不同的类型处理程序)?

没有办法让std::any 成为数组(你可以让std::any 成为std::array,但字符串文字不是std::array),也没有办法让typeid("") 成为指针.但是,您可以使用std::decay_t&lt;decltype("")&gt; 获得与std::any 中存储的相同类型。

【讨论】:

    【解决方案3】:

    字符串文字的类型为const char* 是一种常见的误解。

    它没有。它的类型为const char[&lt;size + 1&gt;](空终止符加一个)。

    例如"" 的类型为 const char[1]

    但我们经常将字符串字面量分配给const char*,这是不合常规的(也因为否则我们会触发导致复制字符串的特殊规则。

    此外,数组名称衰减规则实际上使观察 C 中名称的数组特性变得相当困难(以及,通过扩展,C++); std::any 的工作方式就是一个例子。

    【讨论】:

      猜你喜欢
      • 2015-04-21
      • 1970-01-01
      • 2015-11-18
      • 1970-01-01
      • 2013-04-22
      • 2010-12-31
      • 2020-08-28
      • 1970-01-01
      相关资源
      最近更新 更多