0

次のようなコードを使用しようとすると:

namespace
{
    typedef boost::shared_ptr< float >  sharedFloat;
}

static bool operator<( const sharedFloat& inOne, float inTwo )
{
    return *inOne < inTwo;
}

static void foo()
{
    std::vector< sharedFloat > theVec;
    std::vector< sharedFloat >::iterator i =
        std::lower_bound( theVec.begin(), theVec.end(), 3.4f );
}

エラーが発生します:

error: invalid operands to binary expression ('boost::shared_ptr<float>' and 'float')

( の実装で < 比較へのポインターを使用します。) では、これらのオペランドlower_boundに を指定したのに、なぜ無効なのですか?operator<

代わりに比較関数を使用すると、

namespace
{
    typedef boost::shared_ptr< float >  sharedFloat;

    struct Comp
    {
        bool operator()( const sharedFloat& inOne, float inTwo )
        {
            return *inOne < inTwo;
        }
    };
}

static void foo()
{
    std::vector< sharedFloat > theVec;
    std::vector< sharedFloat >::iterator i =
        std::lower_bound( theVec.begin(), theVec.end(), 3.4f, Comp() );
}

その後、コンパイルします。私はそのように物事を行うことができましたが、最初の試みが失敗した理由を知りたい.

ソリューションの後に追加: Herb Sutter による Namespaces & Interface Principleは、このことをより明確にするのに役立ちました。

4

2 に答える 2

4

は、使用するタイプに関連付けられた名前空間にないため、operator<によって検出されません。lower_bound

コンパイラは名前空間stdとを調べますboostが、そこからは何も関係しないため、グローバル名前空間は調べません。

Compexpliciltyを渡すと、コンパイラは一致する演算子を検索する必要がないため、機能します。

于 2013-03-12T21:31:50.500 に答える
3

への呼び出しは名前空間operator <内で実行されます。stdしたがって、コンパイラは、名前空間とその引数 (ADL) の名前空間で適切なオーバーロードを探しoperator <ますstd。演算子が 1 つ見つかった場合 (実行可能でなくても!)、囲んでいる名前空間は検索されません。

youroperator <はグローバル名前空間で定義されているため、コンパイラはそれを考慮しません (別のオーバーロードが名前空間にoperator <存在し、名前のstdルックアップが名前空間を囲むことを検討する前に見つかったため)。

最後に、std::operator <実行可能でないため、コンパイラはエラーを出力します。

独自のファンクターを最後の引数として渡す場合、状況は明らかに異なります。実行可能な を探す代わりにoperator <、引数自体が呼び出され、すべてが正常にコンパイルされます。

于 2013-03-12T21:24:13.780 に答える