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();
}
[ツッコミを入れる]