5

私は仕事をしていて、関数でコンパレーターを書いていました(後で、どこが最適かを決めたときに移動します)、そしてこの特異性に気づきました。しばらく考えてみたところ、内側のコンパレータを使ってもコードがコンパイルされない理由がよくわからないのですが、外側のコンパレータは問題ありません。

説明はありますか?

クイックテストハーネス:

#include <iostream>
#include <vector>
#include <algorithm>

class CompareMe
{
 public:
    CompareMe(int in) : toCompare(in){}
    int toCompare;
};

class Comparators
{
public:
    bool operator()(CompareMe * first, CompareMe * second)
    {
        return first->toCompare < second->toCompare;
    }
};

class ComparatorsOuter : public Comparators{};

int main()
{
    class ComparatorsInner : public Comparators{};

    std::vector<CompareMe *> compares;
    compares.push_back(new CompareMe(0));
    compares.push_back(new CompareMe(1234));
    compares.push_back(new CompareMe(163));
    compares.push_back(new CompareMe(6));
    compares.push_back(new CompareMe(12));

    //This works, and properly sorts the array
    ComparatorsOuter comparator;
    std::sort(compares.begin(), compares.end(), comparator);

    //Uncomment out the sort below and it will not compile.
    ComparatorsInner comparatorInner;
    //std::sort(compares.begin(), compares.end(), comparatorInner);

    std::vector<CompareMe *>::iterator it;
    for(it = compares.begin(); it != compares.end(); ++it)
    {
        std::cout << (*it)->toCompare << std::endl;
    }
}

sort(__gnu_cxx::__normal_iterator<CompareMe**, std::vector<CompareMe*, std::allocator<CompareMe*> > >, __gnu_cxx::__normal_iterator<CompareMe**, std::vector<CompareMe*, std::allocator<CompareMe*> > >, main()::ComparitorInner&)エラー:' 'の呼び出しに一致する関数がありません

4

2 に答える 2

10

C ++ 03では、テンプレート引数に内部リンクを設定できませんでした。

[C++03: 14.6.4.2/1]:テンプレートパラメータに依存する関数呼び出しの場合、関数名が非修飾IDであるが、テンプレートIDではない場合、候補関数は、次の場合を除いて、通常のルックアップルール(3.4.1、3.4.2)を使用して検出されます。

  • 非修飾名ルックアップ(3.4.1)を使用したルックアップの部分では、テンプレート定義コンテキストからの外部リンケージを持つ関数宣言のみが見つかります。
  • 関連する名前空間(3.4.2)を使用したルックアップの一部では、テンプレート定義コンテキストまたはテンプレートインスタンス化コンテキストのいずれかで見つかった外部リンケージを持つ関数宣言のみが見つかります。

[..]

これは、C ++ 11で変更されました(問題#561:「依存名ルックアップの内部リンケージ関数」 ):

[C++11: C.2.6]:14.6.4.2
変更:内部リンケージを使用して関数の依存呼び出しを許可する理由
過度に制約され、過負荷解決ルールを簡素化します。

その結果:

[C++11: 14.6.4.2/1]:テンプレートパラメータに依存する関数呼び出しの場合、候補関数は、次の点を除いて、通常のルックアップルール(3.4.1、3.4.2、3.4.3)を使用して検出されます。

  • 非修飾名ルックアップ(3.4.1)または修飾名ルックアップ(3.4.3)を使用したルックアップの一部では、テンプレート定義コンテキストからの関数宣言のみが検出されます。
  • 関連する名前空間(3.4.2)を使用したルックアップの一部では、テンプレート定義コンテキストまたはテンプレートインスタンス化コンテキストのいずれかで見つかった関数宣言のみが見つかります。

[..]

(不足している「外部リンケージ付き」の資格を見つけます。)

main()::ComparitorInner&は内部リンケージがあり、のインスタンス化でstd::sortはこのタイプがテンプレートパラメータである必要があるため(推定されますが)、コードはC++11でのみ有効です。

于 2013-01-30T03:12:52.867 に答える
3

コードはC++11で問題ありません。C ++ 03では、テンプレート引数としてローカルタイプを使用することについて制限がありました。

于 2013-01-30T03:10:57.840 に答える