题
我知道编译器在实施方面有很大的自由 std::type_info
功能的行为。
我正在考虑使用它比较对象类型,因此我想确保:
std::type_info::name
必须返回两种不同类型的两个不同的字符串。std::type_info::before
必须说Type1
是 前Type2
独家或Type2
是 前Type1
.// like this: typeid(T1).before( typeid(T2) ) != typeid(T2).before( typeid(T1) )
同一模板类的两个不同的专业化被认为是不同的类型。
两个不同
typedef
- 同一类型的密码是相同的类型。
最后:
自从
std::type_info
是不可复制的,我该如何存储type_info
S某个地方(例如:在std::map
)?它拥有一个std::type_info
总是在某个地方分配(例如:在堆栈或静态/全局变量上)并使用指针?多快
operator==
,operator!=
和before
在最常见的编译器上?我想他们只能比较一个值。以及有多快typeid
?我有一堂课
A
与virtual bool operator==( const A& ) const
. 。自从A
有许多子类(其中一些在编译时未知),我在任何子类中都超载该虚拟操作员B
这边走:virtual bool operator==( const A &other ) const { if( typeid(*this) != typeid(other) ) return false; // bool B::operator==( const B &other ) const // is defined for any class B return operator==( static_cast<B&>( other ) ); }
这是实施该操作员的可接受(和标准)方法吗?
解决方案
快速查看文档后,我会说:
std :: type_info ::名称总是返回两种不同类型的两个不同的字符串,否则意味着编译器在解决类型的同时丢失了自身,您不应该再使用它了。
参考资料告诉:“在返回之前,如果类型在整理顺序中的RHS类型之前。整理顺序只是特定实现的内部顺序,不一定与继承关系或声明的顺序有关。”因此,您可以保证没有类型在整理顺序中具有相同的排名。
模板类的每个实例化都是不同的类型。专业不例外。
我真的不明白你的意思。如果你的意思是像
typedef foo bar;
在两个单独的汇编单元中,这两者都相同,它是这样起作用的。如果你的意思是typedef foo bar; typedef int bar;
, ,它不起作用(除非FOO是INT)。
关于您的其他问题:
- 您应该以某种方式存储对std :: type_info的引用。
- 绝对不知道性能,我认为尽管类型复杂性,但比较操作员仍有恒定的时间。在您的代码中使用的不同类型的数量,必须具有线性复杂性。
- 这真的是iMho。你应该超负荷
operator==
而不是使其虚拟并覆盖它。
其他提示
标准18.5.1(类Type_info):
类Type_info描述了实现生成的类型信息。该类的对象有效地存储了指向该类型名称的指针,以及一个适合比较两种类型的平等或整理顺序的编码值。 类型的名称,编码规则和整理顺序均未指定,并且在程序之间可能有所不同.
从我的理解中:
- 您没有关于
std:type_info::name
. 。该标准仅指出name
返回 实现定义的NTB, ,我相信,一个符合的实现很可能会为每种类型返回相同的字符串。 - 我不知道,而且标准在这一点上尚不清楚,因此我不会依靠这种行为。
- 对我来说应该是明确的“是”
- 对我来说应该是明确的“是”
关于第二组问题:
- 不,你不能存储
type_info
. 。 Andrei Alexandrescu提出了TypeInfo
包装在其中 现代C ++设计 书。注意 返回的对象typeid
有静态存储 因此,您可以安全地存储指针,而不必担心对象寿命 - 我相信你可以假设
type_info
比较非常有效(实际上没有太多比较)。
您可以这样存储。
class my_type_info
{
public:
my_type_info(const std::type_info& info) : info_(&info){}
std::type_info get() const { return *info_;}
private:
const std::type_info* info_;
};
编辑:
C ++标准5.2.8。
TypeID表达式的结果是静态类型const std :: type_info ...的lvalue ...
这意味着您可以这样使用。
my_type_info(typeid(my_type));
TypeID函数返回lvalue(不是临时的),因此返回的type_info的地址始终有效。
问题1和2的当前答案是完全正确的,它们本质上只是type_info类的详细信息 - 重复这些答案没有意义。
对于问题3和4,重要的是要了解C ++的类型是什么,以及它们与名称的关系。对于初学者来说,有很多预定义的类型,这些类型有名字: int, float, double
. 。接下来,有一些构造类型 不是 有自己的名字: const int, int*, const int*, int* const
. 。有功能类型 int (int)
和功能指针类型 int (*)(int)
.
有时将名称命名为未命名类型很有用,可以使用 typedef
. 。例如, typedef int* pint
或者 typedef int (*pf)(int);
. 。这引入了名称,而不是新类型。
接下来是用户定义的类型:结构,类,工会。有一个很好的惯例可以给他们起名字,但这不是强制性的。不要在Typedef中添加这样的名称,您可以直接这样做: struct Foo { };
代替 typedef struct {} Foo;
. 。通常在标题中具有类定义,最终在多个翻译单元中。这确实意味着该类定义不止一次。这仍然是相同的类型,因此您不允许使用宏来更改类成员定义的技巧。
模板类是 不是 一种类型,是类型的食谱。如果模板参数是不同的类型(或值),则单个类模板的两个实例化是不同的类型。这是递归的:给定的 template <typename T> struct Foo{};
, Foo<Foo<int> >
与 Foo<Foo<Bar> >
当且只有 Bar
是类型的另一个名称 int
.
type_info正在定义实现,因此我真的不依赖它。但是,根据我使用G ++和MSVC的经验,假设1,3和4保持...不确定#2。
有什么原因您不能使用这种方法吗?
template<typename T, typename U>
struct is_same { static bool const result = false; };
template<typename T>
struct is_same<T, T> { static bool const result = true; };
template<typename S, typename T>
bool IsSame(const S& s, const T& t) { return is_same<S,T>::result; }