3

テンプレートクラスの明示的なインスタンス化をテストするための短いプログラムを次のように作成しました。

#include <iostream>

template <class T>
struct less_than_comparable {
    friend bool operator>=(T const& a, T const& b) {
        return !(a < b);
    }
};

class Point {
    friend bool operator<(Point const& a, Point const& b) {
        return a.x_ < b.x_;
    }

public:
    Point(int x) : x_(x) {}

private:
    int x_;
};

template struct less_than_comparable<Point>; 
//Here I explicitly instantiate a template class expecting that 
//less_han_comparable<Point> would export opeartor>=() for class Point to the global
//namespace, and then the p1 >= p2 statement will work as expected.

int main() {
    using namespace std;

    Point p1(1), p2(2);
    cout << (p1 < p2) << endl;
    cout << (p1 >= p2) << endl; //But I have a compiler error here saying that 
                                //no match for ‘operator>=’ in ‘p1 >= p2’
}

less_than_comparableからPointを継承する場合、コードはコンパイルに合格します。 しかし、私の質問は、明示的なインスタンス化を使用するとなぜ機能しないのかということです。 Ubuntu10.04で実行されているG++4.4.5を使用しています。コメントをいただければ幸いです。ありがとう。

4

4 に答える 4

2

問題は、クラスのような型の内部で定義されたフレンド関数が、囲んでいる名前空間に注入されないことです。

あなたが参照している原則は「フレンド名注入」と呼ばれますが、これは現在の C++ 標準では「ADL」( Argument Dependent Lookup 、 Koenig Lookupとも呼ばれます) に置き換えられています。ADL は、一致する関数の関数パラメーターの型に関連付けられているすべての名前空間を調べます。

あなたの場合、電話をかけoperator>=たときp1 >= p2(つまりoperator>=(p1, p2);)。ADL は の名前空間で一致する関数を探しますがPoint、そのPointような関数はありません。

Pointから継承すると、の名前空間の一部になりless_than_comparable、ADL はここでそれを見つけることができます。operator>=Point

ここでフレンド名のインジェクションが行われないことを確認できます。

于 2011-04-25T10:38:29.357 に答える
1

Pointを定義したテンプレートクラスではないため、コードは機能しませんoperator >=。このコードをコンパイルする場合はoperator >=、Pointクラスでも定義します。p1p2は、に関連する場所ではないことに注意してくださいless_than_comparable

ちなみに、なぜ「より大きい」演算子の演算子を?の名前で定義したのless_than_comparableですか?

于 2011-04-25T08:26:54.533 に答える
1

明示的なインスタンス化は、コンパイラにその翻訳単位内の特定のテンプレートを強制的にコンパイルさせる方法にすぎません。名前の検索には影響しません。

欲しいと思われるものを手に入れるには、たとえば次のことができます。

class Point : public less_than_comparable<Point> {
于 2011-04-25T08:36:33.130 に答える
0

演算子>=は、コンパイラに関する限り、Pointとは関係のない完全に異なるタイプのメンバー関数です。私はあなたがしたいことは次のとおりだと思います:

template< T >
bool operator >= ( T const& a, T const& b ) {... }

クラスを忘れて、それをグローバル関数にするだけです。また、明示的なテンプレートのインスタンス化は必要ありません。実際、私がそれを使用しているのを見たのは、ライブラリ内でテンプレートクラスを宣言し、別のプロジェクトで使用したときだけでした。これは明らかにここでは行っていません。

于 2011-04-25T08:26:32.467 に答える