LoginSignup
4
1

More than 5 years have passed since last update.

ADLとusingではどっちが優先されるか調べてみた

Last updated at Posted at 2017-03-09

ADLに関して、優先度がどれくらい高いのか実際にコードを書いてみました。
ネットを探せば答えがありそう(というかwikiに答えが載ってました)ですが、自学のためにもコーディング・・・。
なお、ADLとはなんぞや?については参考をみてください。

コード

結論的にはこれなんですが。。。

namespace hoge{

    struct X{
        int a[100];
    };

    int * begin(X& x) { 
        std::cout << "hoge::begin()" << std::endl;
        return x.a;
    }
    int * end(X& x) { return x.a+100; }

}

template < typename Container >
void f(Container && c)
{
    using std::begin;
    using std::end;

    auto iter = begin(c);
    auto enda = end(c);
}


int main(int argc, char* argv[])
{

    std::vector<int> v = { 1, 2, 3, 5 };
    std::cout << "vector" << std::endl;
    f(v);


    int ar[] = { 1, 2, 3, 5 };
    std::cout << "array" << std::endl;
    f(ar);


    hoge::X  a;
    std::cout << "namespace hoge" << std::endl;
    f(a);

    return 0;
}

結果

vector
array
namespace hoge
hoge::begin()

て具合でhoge名前空間内のbeginが呼ばれてます。
つまり上記コードの関数fは、

  • std名前空間で定義されているコンテナはstd::begin、std::endを使い、
  • 配列のときもstd::begin、std::endを使い、
  • 任意名前空間で定義したbegin、endがあれば、それを使う。 というテンプレート関数になります。

なので当然、関数f内の

    using std::begin;
    using std::end;

を削除すると、int ar[]が引数のときにbegin/endの未定義でエラーですし、

    auto iter = std::begin(c);
    auto enda = std::end(c);

と書くと、任意名前空間で定義したbegin、endは呼ばれなくなります。

まとめ

using で定義するよりもADLが優先される。

参考

4
1
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
1