65.9K
CodeProject 正在变化。 阅读更多。
Home

typeof 运算符实现

starIconstarIconstarIcon
emptyStarIcon
starIcon
emptyStarIcon

3.84/5 (8投票s)

2004年8月7日

4分钟阅读

viewsIcon

78707

downloadIcon

359

Visual C++ 7.1 编译器的 typeof 运算符。

引言

C++ 标准中缺少的一个运算符是 typeof 运算符,它返回给定表达式的类型。它通常作为编译器扩展实现,但 Visual Studio 的 C++ 编译器 (7.1) 中仍然缺少它。

详细说明

然而,有一些 typeof 实现可以使用,它们可能都基于 Bill Gibbons 提出的一个非常简单但巧妙的想法 (http://www.accu-usa.org/2000-05-Main.html)。简而言之(如果这很难理解,可以跳过此段),要与 typeof 操作一起使用的每个类型都应单独注册,该注册会部分专门化(通过唯一索引)包含已注册类型的类。除此之外,还会引入一个新的函数重载,它将注册类型作为参数接收,并返回一个大小为先前类中使用的唯一索引的数组作为输出。

现在可以简单地实现 typeof 运算符:您需要一个表达式的类型;使用该表达式作为参数调用函数;计算 sizeof 返回值;将大小放入类模板参数中,并接收存储在那里的类型,该类型等于表达式类型!此外,所有这些都在编译时计算,因此,不需要实际的函数定义,这意味着不会引入额外的代码!这是一个绝妙的主意,后果很小(每个要使用的类型都应该注册,并且编译器速度会受到轻微影响)。

虽然没有文档记录(或者我没有在文档中找到),但似乎 Boost 的 MPL 包含一个 typeof 运算符实现,它适用于上述模式

BOOST_MPL_AUX_REGISTER_TYPE(123, abc);
abc aa1;
BOOST_MPL_AUX_TYPEOF(_, aa1) *aa2 = &aa1;

在我看来,Boost 解决方案的缺点是

  1. 它没有文档记录。
  2. 语法非常难看。
  3. 您必须手动为每个类型的注册过程提供唯一的索引。
  4. 您必须分别注册指针和常量类型。
  5. 如果您想注册模板实例,则必须使用 typedef,因为冒号不能放在 define 宏参数中。
  6. 错误消息不存在。

我已经尝试过,并希望成功地找到了所有列出问题的解决方法。

好了

  1. 你正在看它! :)
  2. 现在语法更清晰了! 类型注册是这样完成的
    register_type hash_table<int, char *> for_typeof;

    ...而用法就像这样简单

    hash_table<int, char *> var;
    typeof(&var) ptr = &var;
    for(typeof(var)::iterator it = var.begin(); it != var.end(); it++)
    

    您可以看到代码变得更具可读性,您必须键入更少的内容,并且在类型(尤其是集合类)更改的情况下,您只需在一个地方进行修改。

    请注意,如果您在注册过程中提供被指针、引用或 const/volatile 修饰符污染的 typedef,它们将被删除。 此外,您可以随意在任何地方使用 typeof 运算符,用于局部变量、全局变量、类成员、基类等等。

  3. 如上所示,您只需要注册期间的类型! 唯一的索引由新 Visual Studio 中的 __COUNTER__ 宏提供。 但是,不要认为这使得实现变得微不足道 - Boost 的预处理器库和模板专门化已被大量使用,因为每次使用 __COUNTER__ 宏都会给您不同的数字,而索引必须在注册过程中的许多地方使用!
  4. 通过使用 Boost 的预处理器库(它同时非常强大但非常有限),该类型的指针会自动注册。 常量 TYPEOF_POINTER_LEVELS(默认为 3)定义将注册多少个指针。 实际上,默认值就足够了。 较高的值(例如 50)会使编译器非常慢,而限制约为 80。 此外,最低级别的 const 修饰符也将被注册(其他组合的实现将非常复杂)。

    为了更清楚起见,注册后,使用默认的 pointer_levels 值,您将能够使用以下类型

    hash_table<int, char *>
    hash_table<int, char *> *
    const hash_table<int, char *> *
    hash_table<int, char *> **
    const hash_table<int, char *> **
    hash_table<int, char *> ***
    const hash_table<int, char *> ***
  5. 已修复,没有其他评论。 :)
  6. 如果您尝试将 typeof 运算符应用于未注册的类型,则在第二个错误消息中,将提到 typeof_type_not_registered 类型,这应该更清楚地说明发生了什么。

我期待看到评论、改进、建议和更简单的解决方案!

要求

(未经先前版本测试)

© . All rights reserved.