typeof演算子 in 標準C

プログラミング言語Cの次期仕様C2x(C23)では、式から型情報を取り出す typeof演算子(typeof operator) が追加される。

// C2x
const int x = /*...*/;
typeof(x) y;  // const int型
typeof_unqual(x) z;  // int型

int func(int);
typeof(func)* pf;  // int(*)(int)型


  • 2種類のtypeof演算子が追加される。
    • typeofオペランドの型情報をそのまま返す。従来からある同名のGCC拡張機能を標準化したもの。
    • typeof_unqualオペランドから型修飾(type qualifiers)を除去*1した型情報を返す。
    • C2x typeof_unqual(E)C++ std::remove_cvref_t<decltype(E)>*2
  • typeof演算子は 式(expression) または 型名(type-name) を対象とする。
    • sizeof演算子とは異なり*3、typeof演算子に式を指定する場合も括弧は必須。
  • C言語typeof != C++言語のdecltype
    • C2x typeofは型名も指定可能/C++decltypeは式のみサポート。
    • C言語には参照型(reference type)が存在しないため、オペランドの括弧有無により両者の挙動が異なる。

typeof(C) vs. decltype(C++)


int x;  // int

// C2x
typeof( x ) y0;  // int
typeof((x)) y1;  // int

// C++
decltype( x ) z0;  // int
decltype((x)) z1;  // int&(参照型)

C++11 decltype検討時の提案文書N1607*4でもGCC拡張機能typeofにおける参照型の扱いを取り上げ、それとは異なる動きをするキーワードとしてC++へ導入した経緯がある。

3 Design alternatives for typeof
Two main options for the semantics of a typeof operator have been discussed: either to preserve or to drop references in types.
A reference-dropping typeof always removes top-level references. Some compiler vendors (EDG, Metrowerks, GCC) provide a typeof operator as an extension with reference-dropping semantics. This appears to be a reasonable semantics for expressing the type of variables. On the other hand, the reference-dropping semantics fails to provide a mechanism for exactly expressing the return types of generic functions, as demonstrated by Stroustrup. This implies that a reference-dropping typeof would cause problems for writers of generic libraries.
Therefore, we propose that the operator be named decltype.


*1:トップレベルの const, volatile, restrict(→id:yohhoy:20120223), _Atomic の4種類全てが除去される。C言語の _Atomic キーワードには、指定子 _Atomic(T) と 修飾子 _Atomic T の2種類の用法があるが、typeof_unqual は両者を区別せずに除去する。

*2:C++言語仕様には restrict 修飾子は存在しない。またC++のatomic変数はクラステンプレート std::atomic<T> として定義され、C言語のような _Atomic キーワードが存在しない。