我知道编译器在实施方面有很大的自由 std::type_info 功能的行为。

我正在考虑使用它比较对象类型,因此我想确保:

  1. std::type_info::name 必须返回两种不同类型的两个不同的字符串。

  2. std::type_info::before 必须说 Type1 Type2 独家或 Type2 Type1.

    // like this:
    typeid(T1).before( typeid(T2) ) != typeid(T2).before( typeid(T1) )
    
  3. 同一模板类的两个不同的专业化被认为是不同的类型。

  4. 两个不同 typedef- 同一类型的密码是相同的类型。

最后:

  • 自从 std::type_info 是不可复制的,我该如何存储 type_infoS某个地方(例如:在 std::map)?它拥有一个 std::type_info 总是在某个地方分配(例如:在堆栈或静态/全局变量上)并使用指针?

  • 多快 operator==, operator!=before 在最常见的编译器上?我想他们只能比较一个值。以及有多快 typeid?

  • 我有一堂课 Avirtual 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 ) );
    }
    

    这是实施该操作员的可接受(和标准)方法吗?

有帮助吗?

解决方案

快速查看文档后,我会说:

  1. std :: type_info ::名称总是返回两种不同类型的两个不同的字符串,否则意味着编译器在解决类型的同时丢失了自身,您不应该再使用它了。

  2. 参考资料告诉:“在返回之前,如果类型在整理顺序中的RHS类型之前。整理顺序只是特定实现的内部顺序,不一定与继承关系或声明的顺序有关。”因此,您可以保证没有类型在整理顺序中具有相同的排名。

  3. 模板类的每个实例化都是不同的类型。专业不例外。

  4. 我真的不明白你的意思。如果你的意思是像 typedef foo bar; 在两个单独的汇编单元中,这两者都相同,它是这样起作用的。如果你的意思是 typedef foo bar; typedef int bar;, ,它不起作用(除非FOO是INT)。

关于您的其他问题:

  • 您应该以某种方式存储对std :: type_info的引用。
  • 绝对不知道性能,我认为尽管类型复杂性,但比较操作员仍有恒定的时间。在您的代码中使用的不同类型的数量,必须具有线性复杂性。
  • 这真的是iMho。你应该超负荷 operator== 而不是使其虚拟并覆盖它。

其他提示

标准18.5.1(类Type_info):

类Type_info描述了实现生成的类型信息。该类的对象有效地存储了指向该类型名称的指针,以及一个适合比较两种类型的平等或整理顺序的编码值。 类型的名称,编码规则和整理顺序均未指定,并且在程序之间可能有所不同.

从我的理解中:

  1. 您没有关于 std:type_info::name. 。该标准仅指出 name 返回 实现定义的NTB, ,我相信,一个符合的实现很可能会为每种类型返回相同的字符串。
  2. 我不知道,而且标准在这一点上尚不清楚,因此我不会依靠这种行为。
  3. 对我来说应该是明确的“是”
  4. 对我来说应该是明确的“是”

关于第二组问题:

  • 不,你不能存储 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; }
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top