我正在制作一个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)进行测试。
答案 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 );
在这种情况下,T
是const 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
的工作方式就是一个例子。