我知道编译器可以很自由地实现std::type_info
函数的行为。
我正在考虑使用它来比较对象类型,所以我想确定:
std::type_info::name
必须为两种不同的类型返回两个不同的字符串。
std::type_info::before
必须说Type1
之前 Type2
exclusive-or Type2
< em>之前 Type1
。
// like this:
typeid(T1).before( typeid(T2) ) != typeid(T2).before( typeid(T1) )
同一模板类的两种不同特化被认为是不同的类型。
两种不同的typedef
- 相同类型的相同类型。
最后:
由于std::type_info
不可复制,我如何将type_info
存储在某处(例如:在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 ) );
}
这是实现此类运营商的可接受(和标准)方式吗?
答案 0 :(得分:8)
快速浏览一下文档后,我会说:
std :: type_info :: name总是为两种不同的类型返回两个不同的字符串,否则就意味着编译器在解析类型时会自行丢失,你不应再使用它了。
引用告诉:“如果类型在整理顺序中的rhs类型之前,则返回true。归类顺序只是由特定实现保留的内部顺序,并不一定与继承关系或声明顺序相关“。 因此,您可以保证在整理顺序中没有类型具有相同的排名。
模板类的每个实例化都是不同的类型。专业化不例外。
我真的不明白你的意思。如果您的意思是在两个单独的编译单元中使用typedef foo bar;
并且两者中的条形图相同,那么它就是这样的。如果你的意思是typedef foo bar; typedef int bar;
,它就不起作用(除非foo是int)。
关于您的其他问题:
operator==
而不是将其设为虚拟并覆盖它。答案 1 :(得分:4)
标准18.5.1(Class type_info):
类type_info描述类型 由...产生的信息 实现。这个类的对象 有效地存储指向名称的指针 对于类型和编码值 适合比较两种类型 平等或整理顺序。的的 名称,编码规则和整理 类型的序列都是未指定的 程序之间可能有所不同。
根据我的理解:
std:type_info::name
没有此保证。该标准仅声明name
返回实现定义的NTBS ,并且我相信符合标准的实现可以为每种类型返回相同的字符串。关于第二组问题:
type_info
。 Andrei Alexandrescu在其Modern C++ Design书中提出了TypeInfo
封面。请注意, typeid
返回的对象具有静态存储,因此您可以安全地存储指针而无需担心对象生存期type_info
比较非常有效(实际上没有太多可比性)。答案 2 :(得分:3)
您可以像这样存储它。
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表达式是一个左值 static类型const std :: type_info ...
这意味着您可以像这样使用它。
my_type_info(typeid(my_type));
typeid函数返回一个左值(它不是临时的),因此返回的type_info的地址始终有效。
答案 3 :(得分:1)
问题1和2的当前答案是完全正确的,它们基本上只是type_info类的详细信息 - 没有必要重复这些答案。
对于问题3和4,了解C ++中的类型究竟是什么以及它们与名称的关系非常重要。对于初学者,有一大堆预定义类型,其名称为int, float, double
。接下来,有些构造类型 not 具有自己的名称: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
的另一个名称。
答案 4 :(得分:0)
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; }