標準で含まれている C++ ライブラリのロードにより、オブジェクトをライブラリで使用するように適合させることができます。多くの場合、同じ名前空間内のメンバー関数またはフリー関数のどちらかを選択します。
ライブラリコードがこれらの「拡張」関数の1つを呼び出す呼び出しをディスパッチするために使用するメカニズムと構成を知りたいのですが、この決定はコンパイル時に行う必要があり、テンプレートが関係していることを知っています。次のランタイム疑似コードは不可能/無意味です。理由はこの質問の範囲外です。
if Class A has member function with signature FunctionSignature
choose &A.functionSignature(...)
else if NamespaceOfClassA has free function freeFunctionSignature
choose freeFunctionSignature(...)
else
throw "no valid extension function was provided"
上記のコードは、ランタイム コードのように見えます:/. では、ライブラリはクラスが存在する名前空間をどのように把握するのか、3 つの条件をどのように検出するのか、回避する必要があるその他の落とし穴にはどのようなものがあるのでしょうか。
私の質問の動機は、ライブラリでディスパッチ ブロックを見つけ、自分のコードで構成を使用できるようにすることです。したがって、詳細な回答が役立ちます。
!!報奨金を獲得するために!!
わかりましたので、Steve からの回答 (およびコメント) によると、ADL と SFINAE は、コンパイル時にディスパッチを配線するための重要な構成要素です。私は ADL (基本的に) と SFINAE (これも初歩的) の周りに頭を抱えています。しかし、私が思うように、彼らがどのように組織化されているかはわかりません。
オブジェクト内のユーザー提供のメンバー関数を呼び出すか、同じオブジェクトの名前空間で提供されるユーザー提供の自由関数を呼び出すかを、ライブラリがコンパイル時に選択できるように、これら 2 つの構造を組み合わせる方法の例を示したいと思います。これは、上記の 2 つの構成体を使用してのみ行う必要があり、いかなる種類のランタイム ディスパッチも使用しないでください。
問題のオブジェクトが と呼ばれNS::Car
、このオブジェクトが の動作をMoveForward(int units)
メンバー関数 ofc として提供する必要があるとします。動作がオブジェクトの名前空間から取得される場合、おそらく のようになりますMoveForward(const Car & car_, int units)
。をディスパッチしたい関数を定義しましょうmover(NS::direction d, const NS::vehicle & v_)
。ここで、方向は列挙型で、v_ は の基底クラスですNS::car
。