2016年04月06日(水) [長年日記]
■ [c++] C++で型名と変数名を同じにしてみる
C++で型名と変数名を同じにしたいときにどうするか。
サンプルコード
次のように、クラスouter内にinnerと言う名前のクラスとメンバ変数を両方定義してみる。
#include <iostream> struct outer { struct inner { void f() { std::cout << "hello" << std::endl; } }; inner inner; }; int main() { outer::inner a; a.f(); }
このコードはコンパイルエラーになる(g++ 4.8.5を使用)。main()内の「outer::inner」はクラス名ではなくメンバ変数名と解釈される。
次のように struct を補うとコンパイルできるようになる。
int main() { struct outer::inner a; a.f(); }
別名を使う
struct outer::inner は長いので、エイリアス宣言を使って別名を定義してみる。
int main() { using in = struct outer::inner; in a; a.f(); }
このコードは動作するが、g++は
warning: declaration 'struct outer::inner' does not declare anything [enabled by default]
という警告を出力する。とはいえ、structを省いて「using in = outer::inner;」と書くとコンパイルできない。警告が出るのはg++のバグである気がする。clangを使うと警告は出力されない。
試しにstructの代わりに「using in = typename outer::inner;」とtypenameを書いてみたら、g++ではコンパイルできた。しかし、clangではコンパイルエラーになる。この書き方は不正なのだろうと思われる。
g++でもclangでも警告なしにコンパイルするには、エイリアス宣言ではなくtypedefを使えばよい。
int main() { typedef struct outer::inner in; in a; a.f(); }