メモの日々


2016年12月27日(火) [長年日記]

[c++] C++で型名とメンバ関数名を同じにしてみる

型名と変数名を同じにしたときの話を以前にメモしたが、型名とメンバ関数名を同じにしたときのGCCの挙動もメモ。型名を小文字で書いていると変数や関数や名前空間名との衝突が起こりがち。

サンプルコード

#include <iostream>

namespace ns {
  struct value {
    int v;
  };

  struct holder {
    value val;
    const value& value() const { return val; }
  };
}

int main() {
  ns::holder h{ns::value{100}};
  std::cout << h.value().v << std::endl;
}

このコードはclang 3.8だとコンパイルできるが、g++ 6.1では次のコンパイルエラーになる。

prog.cc:10:46: error: declaration of 'const ns::value& ns::holder::value() const' [-fpermissive]
     const value& value() const { return val; }
                                              ^
prog.cc:4:10: error: changes meaning of 'value' from 'struct ns::value' [-fpermissive]
   struct value {
          ^~~~~

名前空間名を補うとg++でもコンパイルできるようになる

次のように名前空間名を補って struct value を使うんだという意思を示すとg++でもコンパイルできる。

@@ -6,8 +6,8 @@
   };

   struct holder {
-    value val;
-    const value& value() const { return val; }
+    ns::value val;
+    const ns::value& value() const { return val; }
   };
 }

メンバ関数value()の宣言だけでなく、メンバ変数valの型にも名前空間名を補わないとコンパイルエラーになるのが分かりにくい。