2016-01-18 13 views
5

questionがあり、C++のpriority_queueでコンパレータを使用する方法について説明しています。彼は第3引数としてオーバーロードされたoperatorclass(またはstruct)を与え、正常に動作します。しかし、bool機能が動作しません。どうして ?しかし<algorithm>sortで正常に動作します。ドキュメント(priority_queue & & algo/sort)を調べると、両方ともオプションの第3引数としてclass Compareが使用されます。関数コンパレータがソートのように優先度キューで動作しないのはなぜですか?

#include <iostream> 
#include <cstdio> 
#include <queue> 
#include <algorithm> 
#include <vector> 

using namespace std; 

bool cmp (const int &a,const int &b){ return a > b; } 

struct cmp2 
{ 
    bool operator() (const int &p1,const int &p2) 
    { 
     return p1 > p2; 
    } 
}; 

int main() 
{ 
// freopen("test.txt","r",stdin); 
    int a[10]; 
    vector<int> b(10); 
    sort(a , a + 10, cmp); // working cool 
    sort(b.begin() , b.end() , cmp); // working great 
    priority_queue<int, vector<int> , cmp2 > x; // as usual, working.... 
    priority_queue<int, vector<int> , cmp > y; // not working why ? 

    return 0; 
} 

エラー:

A:\pqvsarray.cpp In function 'int main()': 
27 40 A:\pqvsarray.cpp [Error] type/value mismatch at argument 3 in template parameter list for 'template<class _Tp, class _Sequence, class _Compare> class std::priority_queue' 
27 40 A:\pqvsarray.cpp [Error] expected a type, got 'cmp' 
27 43 A:\pqvsarray.cpp [Error] invalid type in declaration before ';' token 

それでは、なぜ違いは?

+1

priority_queueテンプレートには型が必要ですが、関数ポインタを指定しているためです。 –

+0

なぜ、 'sort'は'関数ポインタ 'を取るのですか? – azam

+1

@SelçukCihan[priority_queueのドキュメント](http://www.cplusplus.com/reference/queue/priority_queue/)によれば、関数ポインタにすることができます:*これは関数ポインタまたは関数オブジェクトです。* – Aracthor

答えて

3

std::priority_queueの機能も使用できます。あなたが何をしているの違いは、関数パラメータとしてstd::sortに関数を渡すが、関数をキューのテンプレートパラメータとして定義しようとします。これは、エラーが説明するように、第3引数が型引数であるため、明らかに機能しません。また、ポインタや参照テンプレート引数を持つことさえできません。

referenceを見ると、キューには比較オブジェクトを渡すためのコンストラクタがあることがわかります。 それはです。この関数を渡す必要があります。

std::sortとの違いがあります。ソートは関数であり、コンパイラにテンプレート引数であるため、明示的に指定する必要はありません。キューはクラステンプレートであり、クラステンプレートのテンプレート引数は推測できません(この文脈では少なくともありません)。

テンプレート引数のデフォルトはstd::less<typename Container::value_type>ですが、そのテンプレートは使用しません。したがって、比較オブジェクトの型を明示的に指定する必要があります。オブジェクトを渡そうとしている場所を指定します。どのように関数のポインタ/参照の型を取得するには、尋ねることがあります。あなたはこのようにすることができます:decltype(&cmp)decltypeをまだサポートしていない古いコンパイラがある場合は、それを除いてタイプを指定する必要があります:bool (&)(const int&, const int&)

ここでは、関数を使用するキューを作成する方法の例を示します。

std::priority_queue<int, std::vector<int>, decltype(&cmp)> x(cmp); 
+0

はい、 'bool(&)(const int&、const int&)'が3番目の引数として機能しています。 'decltype'は私が間違っていないとC++ 11にあります。そして説明を良くするため+1。 – azam

+0

うん、 'decltype'が実際にC++ 11で追加されました。 – user2079303

1

答えはコンパイラエラーです。 優先度キューの3番目のテンプレートパラメータは、コンパイラタイプ(構造体やクラスなど)であり、関数ではありません。

+1

[priorty_queueのドキュメント](http://www.cplusplus.com/reference/queue/priority_queue/)によれば、関数を使用することが可能でなければなりません。 – Aracthor

+1

@Aracthor:可能です。正しい引数を適切な場所に渡すだけです。 'priority_queue'のテンプレート引数として関数ポインタの型を渡し、実際の関数ポインタをコンストラクタの引数として渡します。これは 'std :: sort'とまったく同じ状況ですが、型が推測される点を除いて、関数テンプレート(' std :: sort'のようなもの)の呼び出しではできますが、クラステンプレートオブジェクトのインスタンス化( 'std :: priority_queue'など) –

+0

"* Why?*"について少し説明した方が良いでしょう。しかし、ありがとう! – azam

2

エラーメッセージが示すように、関数をテンプレートパラメータとして使用することはできません。 priority_queueは、比較タイプののオブジェクトをコピーします。たとえば、これはstd::less<int>で、そのタイプのオブジェクトはstd::less<int>()であり、呼び出されるのはstd::less<int>()(x, y)です。 C++ 11では、decltypeを使うことができましたが、C++ 03では、関数オブジェクトとして使用するために用意された「ファンクタ」を作成することが「正規の」方法です。 lambdasが作成されました。

+0

C++の欠点を発見し、C++ 11で 'lambda'sの出現の理由を説明するために、ニース。 – azam

関連する問題