1. ホーム
  2. c++

[解決済み] Argument-Dependent Lookup」(別名ADL、「Koenig Lookup」)とは何ですか?

2022-04-30 04:35:29

質問

引数依存型ルックアップとは何か、何か良い説明はありますか?また、多くの人がケーニッヒ・ルックアップと呼んでいます。

できれば知りたいです。

  • なぜ良いことなのでしょうか?
  • なぜ悪いのですか?
  • どのように機能するのですか?

解決方法は?

ケーニッヒルックアップ または 引数依存型ルックアップ は、C++で非修飾名がコンパイラによってどのようにルックアップされるかを説明しています。

C++11標準§3.4.2/1には、以下のように記載されています。

関数呼び出しの後置表現 (5.2.2) が unqualified-id の場合、通常の非限定検索 (3.4.1) では考慮されない他の名前空間が検索され、その名前空間で、他の方法では見えない名前空間スコープの友人関数宣言 (11.3) が見つかる場合があります。検索に対するこれらの変更は,引数の型に依存します(そして,テンプレートテンプレート引数の場合は,テンプレートテンプレートの名前空間に依存します)。 引数)。

もっと簡単に言うと、ニコライ・ヨスッティは次のように述べています。 1 :

1つ以上の引数型が関数の名前空間で定義されている場合、関数の名前空間を修飾する必要はありません。

簡単なコード例です。

namespace MyNamespace
{
    class MyClass {};
    void doSomething(MyClass) {}
}

MyNamespace::MyClass obj; // global object


int main()
{
    doSomething(obj); // Works Fine - MyNamespace::doSomething() is called.
}

上記の例では using -宣言と using -ディレクティブを使用しても、コンパイラは未修飾の名前を正しく認識します。 doSomething() で宣言された関数として、名前空間 MyNamespace を適用することで ケーニッヒルックアップ .

どのように機能するのですか?

このアルゴリズムは、ローカルスコープだけでなく、引数の型を含む名前空間も見るようにコンパイラに指示する。したがって、上記のコードでは、コンパイラはオブジェクトの obj 関数の引数である doSomething() に属し、名前空間 MyNamespace . そのため、その名前空間を検索して doSomething() .

ケーニッヒルックアップのメリットは何ですか?

上の簡単なコード例が示すように、ケーニッヒ参照はプログラマーに便利さと使いやすさを提供します。ケーニッヒ検索がなければ、プログラマーは完全修飾名を何度も指定したり、代わりに多数の using -を宣言しています。

ケーニッヒルックアップの批判はなぜ?

ケーニッヒ・ルックアップに過度に依存すると、意味上の問題が発生し、プログラマが不意を突かれることがある。

の例を考えてみましょう。 std::swap これは、2つの値を交換する標準的なライブラリアルゴリズムです。ケーニッヒ検索では、このアルゴリズムを使用する際に注意しなければならないことがあります。

std::swap(obj1,obj2);

と同じ挙動を示さない場合があります。

using std::swap;
swap(obj1, obj2);

ADLでは、どのバージョンの swap 関数が呼び出されるかどうかは、渡された引数の名前空間によって決まります。

もし、名前空間 A で、もし A::obj1 , A::obj2 および A::swap() が存在する場合、2番目の例では、結果として A::swap() これは、ユーザーが望んでいたものとは異なるかもしれません。

さらに、何らかの理由で A::swap(A::MyClass&, A::MyClass&)std::swap(A::MyClass&, A::MyClass&) が定義されている場合、最初の例では std::swap(A::MyClass&, A::MyClass&) が、2番目のものはコンパイルされません。 swap(obj1, obj2) は曖昧になる。

トリビアです。

なぜ「ケーニッヒ・ルックアップ」と呼ばれるのですか?

元AT&Tやベル研究所の研究者やプログラマーが考案したものだからです。 アンドリュー・ケーニッヒ .

さらに読む


<サブ ** 1 ** ケーニッヒ・ルックアップの定義は、Josuttis氏の著書「The C++ Standard Library」で定義されている通りです。A Tutorial and Reference*に定義されています。