decltype和typeof有什么区别?

42

关于 decltypetypeof 的两个问题:

  • decltypetypeof 运算符有什么区别吗?
  • C++11 中是否弃用了 typeof

18
请记住,typeof从来没有成为标准。 - GManNickG
7
一个存在,另一个不存在 :-) 还要注意的是,decltype 有着明确定义且有趣的语义,它允许你在非常普遍的情况下说出像 decltype(x)&& 这样的话。 - Kerrek SB
@GManNickG,更新内容在C23。 - undefined
5个回答

35

c++中没有typeof运算符。 虽然大多数编译器一直提供了这样的功能,但它始终是编译器特定的语言扩展。因此,通常比较两者的行为是没有意义的,因为typeof(如果它确实存在)的行为极度依赖于平台。

由于我们现在有了一种标准方式来获取变量/表达式的类型,所以真的没有理由依赖于不可移植的扩展,因此我会说它已经过时了。

另一个需要考虑的问题是,如果某个编译器的typeof行为与decltype不兼容,那么typeof扩展未来可能无法涵盖新的语言特性(这意味着它可能根本无法与例如lambda一起使用)。 我不知道当前是否出现了这种情况,但这是一个明显的可能性。


2
仅仅因为 decltype 这种语法存在,并不意味着 typeof 已经过时,因为 typeof 在 gcc、EDG 和 Metroworks 中的引用去除语义对于声明该类型的本地变量非常有用。然而,现在与 auto 结合使用,它已经变得相当不必要了。遗憾的是,由于现有实现差异的缘故,我们不能使用理想命名的 typeof(与 alignofsizeof 押韵)。 - Dwayne Robinson

25
两者之间的区别在于decltype始终将引用作为信息的一部分保留,而typeof可能不会。所以...
int a = 1;
int& ra = a;
typeof(a) b = 1;     // int
typeof(ra) b2 = 1;   // int
decltype(a) b3;      // int
decltype(ra) b4 = a; // reference to int

“typeof”这个名称是首选(与“sizeof”和“alignof”一致,并且在扩展中已经使用了该名称),但正如您在提案N1478中所看到的,对现有实现中引用丢失的兼容性的担忧使他们决定给它一个不同的名称:
“我们在一般情况下使用运算符名称typeof来指代查询表达式类型的机制。decltype运算符指的是typeof的建议变体...一些编译器供应商(EDG、Metrowerks、GCC)提供了一个具有引用丢失语义的typeof运算符作为扩展。如第4节所述,这似乎非常适合表示变量的类型。另一方面,引用丢失语义无法提供准确表示通用函数返回类型的机制...在本提案中,提供表达式类型信息的运算符的语义反映了声明的类型。因此,我们建议将该运算符命名为decltype。”
J. Jarvi, B. Stroustrup, D. Gregor, J. Siek: Decltype和auto。N1478/03-0061。
所以说decltype完全取代了typeof是不正确的(如果你想要去除引用语义,那么在这些编译器中,typeof扩展仍然有用),而是,decltype加上auto主要取代了typeof,它可以去除引用并替代typeof用于变量推断的用法。
更新日期2023-01-03,显然C23将正式获得typeof功能。在N2927中有相关信息。
更新日期2023-08-28,对于C++26,有p2958r0

10

对于遗留代码,我一直成功地使用以下内容:

#include <type_traits>
#define typeof(x) std::remove_reference<decltype((x))>::type

为什么要多加一对括号?decltype(x)decltype((x))之间的区别通常只是多了一些&,而你最终还是会将其删除?或者我漏掉了什么? - Yakk - Adam Nevraumont
额外的括号是为了防止参数x中未被屏蔽的逗号,但只有在decltype是宏的情况下才会构成威胁。它们的必要性是有争议的。 - user377178
4
如果你想让 C 预处理器正确解析 bob<int, char> 这样的参数,你还需要使用 ...__VA_ARGS__ - Yakk - Adam Nevraumont
好处是,否则需要在 typeof 的参数周围使用额外的括号, 然而,如果 decltype 宏遵循 ... 方案,则不需要在 decltype((x)) 中使用额外的括号。 - user377178

1

嗯,typeof是一种非标准的GNU C扩展,你可以在GNU C++中使用它,因为GCC允许你在另一种语言中使用其他语言的特性(不总是如此),所以它们真的不应该被比较。

当然,其他编译器可能存在其他非标准扩展,但是GCC绝对是最广泛记录的实现。

回答这个问题:如果它从未成为一个特性,那么它就不能过时。

如果你想在C ++中比较两种方法的优点,除非你处理引用,语义上没有区别。你应该使用decltype,因为它是可移植和符合标准的。


0

typeof尚未标准化,尽管它已被一些编译器供应商实现,例如GCC。 它已经过时,可以使用decltype。

关于typeof的缺点,可以在这个相关答案中找到很好的解释。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接