typeid(“”)!= typeid(const char *)

时间:2019-06-12 14:15:49

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

我正在制作一个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(标签/ RELEASE_800 / final)进行测试。

3 个答案:

答案 0 :(得分:17)

正如其他人提到的那样,字符串文字""的类型为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(&)[1](字符串文字""的类型),因此std::decay_t<const char(&)[1]>将给您const char*,即为什么typeid()的{​​{1}}是std::any("").type()的类型ID。

答案 1 :(得分:4)

  

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

根据以下reference

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

4)构造一个对象,该对象的初始内容是类型为std::decay_t<ValueType>的对象,该对象是从std::forward<ValueType>(value)直接初始化的。

std::decay_t<const char[1]>const char*


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

  

[{std::any]甚至不用于“任何对象”。正如我之前所说,我期望“ any”一词是“任何一流的对象类型”(即cv不合格的非数组对象类型)的缩写,但是std::any对CopyConstructible进行了进一步的改进。值类型,因此实际上是“任何可复制的cv不合格非数组对象类型”。

就这样

  

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

无法拥有std::any的数组(您可以拥有std::any的{​​{1}},但是字符串文字不是std::array),也没有办法使std::array成为指针。但是,您可以使用typeid("")来获得与存储在std::decay_t<decltype("")>中的相同类型。

答案 2 :(得分:2)

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

不是。它的类型为const char[<size + 1>](为空终止符加一个)。

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

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

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