

下記コードを実行する際、namespace でくくったはずの関数がそのまま使用できてしまうのは  
namespace の仕様なのでしょうか？  
namespace Test 内で宣言した Vector2 構造体を使用しているか否かで  
コンパイル時の成否が変わってしまっています。  
AddVector() には Test:: を付けても付けなくてもコンパイルが成功してしまっているのが解せません。

AddVector() 自身を namespace Util{} など別名でくくると  
コンパイル時  
Util::AddVecro(); // NG  
Test::Util::AddVector(); // OK  
となります。

[code]

    #include <stdlib.h>
    
    namespace Test {
        struct Vector2 {
            float x;
            float y;
        };
    
        float AddFloat(float a, float b) {
            return a + b;
        }
    
        Vector2 AddVector(const Vector2& srcA, const Vector2& srcB) {
            Vector2 add;
            add.x = srcA.x + srcB.x;
            add.y = srcA.y + srcB.y;
            return add;
        }
    }    // namespace Test
    
    int main(int argc, char *argv[] ) {
        float floatTest[2];
        float floatAdd1 = AddFloat(floatTest[0], floatTest[1]);    // NG
        float floatAdd2 = Test::AddFloat(floatTest[0], floatTest[1]);    // OK
    
        Test::Vector2 test[2];
        Test::Vector2 add;
        add = AddVector(test[0], test[1]);    // OK
    
        return 0;
    }
    
[/code]


CC BY-SA 3.0
2017-08-03T09:53:16.467
36900
2017-08-03T13:26:09.170
24716
question
c++
c++ namespaceの仕様について


[ADL;
実引数依存の名前探索](https://ja.wikipedia.org/wiki/%E5%AE%9F%E5%BC%95%E6%95%B0%E4%BE%9D%E5%AD%98%E3%81%AE%E5%90%8D%E5%89%8D%E6%8E%A2%E7%B4%A2)という機能です。

>
[code]

>     add = AddVector(test[0], test[1]);
>  
[/code]

ですが、第一引数`test[0]`の型は`Test::Vector2`ですので、`Test::AddVector()`が検索されます。

Wikipediaでも説明されていますが、

[code]

    std::cout << "hello, world.\n";
    
[/code]

ですら、名前空間を指定していないにも関わらず`std::operator<<()`を呼び出しているわけで、知らず知らずのうちに使っています。


CC BY-SA 3.0
2017-08-03T10:07:54.393
36901
2017-08-03T10:34:22.067
2017-08-03T10:34:22.067
4236
4236
36900
answer


sayuriさん回答の通り、C++言語の ADL(argument dependent name lookup)
という仕様によって`Test::AddVector`が自動的に探し出されています。

* * *

質問中にあるようなソースコードをコンパイルエラーとしたい場合、下記のように入れ子の名前空間と`using
namespace`宣言を組み合わせることで、明示的にADLを禁止できます。

[code]

    namespace Test {  
      struct Vector2 {
        float x;
        float y;
      };
    
      namespace adl_barrier {
        // 入れ子名前空間内で関数を定義しておき...
        Vector2 AddVector(const Vector2& srcA, const Vector2& srcB) {
          Vector2 add;
          add.x = srcA.x + srcB.x;
          add.y = srcA.y + srcB.y;
          return add;
        }
      }
      // ...改めて入れ子名前空間を取り込む
      using namespace adl_barrier;
    } // namespace Test
    
    int main(int, char *[]) {
      Test::Vector2 test[2];
      Test::Vector2 add;
      add = AddVector(test[0], test[1]);  // NG!
      // ADLは機能しないためAddVectorは見つからない
    
      // 明示的に名前空間修飾を行えばもちろんOK
      // add = Test::AddVector(test[0], test[1]);
    }
    
[/code]


CC BY-SA 3.0
2017-08-03T13:26:09.170
36907
2017-08-03T13:26:09.170
49
36900
answer