2016-01-18 16 views
5

Abbiamo un question, che spiega come utilizzare un comparatore in priority_queue in C++. Dà il sovraccarico operatorclass (o struct) come terzo argomento e funziona correttamente. Ma la funzione bool non funziona. Perché ? Ma funziona bene nello sort dello <algorithm>. Quando ho esaminato i documenti (priority_queue & & algo/sort), entrambi considerano lo class Compare come terzo argomento opzionale.Perché il comparatore di funzioni non funziona nella coda di priorità come fa in ordinamento?

#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; 
} 

Errori:

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 

Quindi, perché la differenza?

+1

Perché il modello priority_queue richiede un tipo, ma si sta assegnando un puntatore a funzione. –

+0

Quindi, come/perché 'sort' prende un' function pointer'? – azam

+1

@ SelçukCihan Secondo [la documentazione priority_queue] (http://www.cplusplus.com/reference/queue/priority_queue/), può essere un puntatore a funzione: * Questo può essere un puntatore a funzione o un oggetto funzione * – Aracthor

risposta

3

È anche possibile utilizzare una funzione con std::priority_queue. La differenza in ciò che si sta facendo è che si passa la funzione a std::sort come parametro di funzione, ma si tenta di definire la funzione come parametro del modello della coda. Questo ovviamente non funziona perché il terzo argomento è un argomento di tipo, come spiega l'errore. Inoltre, non puoi nemmeno avere argomenti di puntatore o modello di riferimento.

Se date un'occhiata allo reference, troverete che la coda ha un costruttore per passare l'oggetto di confronto. Questo è in cui è necessario passare la funzione.

C'è una differenza con std::sort. L'ordinamento è una funzione e puoi lasciare al compilatore deduce gli argomenti del modello in modo da non doverli specificare esplicitamente. La coda è un modello di classe e non è possibile dedurre argomenti modello di un modello di classe (non almeno in questo contesto).

L'argomento del modello è impostato su std::less<typename Container::value_type>, ma non si desidera utilizzarlo. Pertanto, è necessario specificare esplicitamente il tipo dell'oggetto di confronto. Lo specifichi dove stai ora cercando di passare l'oggetto. Come ottenere il tipo di puntatore/riferimento della funzione, è possibile chiedere. Puoi farlo in questo modo: decltype(&cmp). Se si dispone di un compilatore non aggiornato che non supporta ancora decltype, sarà necessario specificare il tipo senza: bool (&)(const int&, const int&).

Ecco un esempio di come si creerebbe una coda che utilizza la propria funzione.

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

Sì, 'bool (&) (const int &, const int &)' mentre il terzo argomento funziona. 'decltype' è in C++ 11 se non sbaglio. E +1 per spiegare bene. – azam

+0

Yup, 'decltype' è stato aggiunto in C++ 11. – user2079303

1

La risposta è negli errori del compilatore. Il terzo parametro template della coda di priorità è un tipo di comparatore (come struttura o classi) e non una funzione.

+1

In base alla [documentazione di priorty_queue] (http://www.cplusplus.com/reference/queue/priority_queue/), dovrebbe essere possibile utilizzare una funzione. – Aracthor

+1

@Aracthor: è possibile. Devi solo passare l'argomento giusto al posto giusto. Si passa il tipo del puntatore alla funzione come argomento modello per 'priority_queue' e si passa il puntatore alla funzione effettiva come argomento al costruttore. Questa è esattamente la stessa situazione che si ha con 'std :: sort', eccetto lì, il tipo è dedotto, che si può fare con una chiamata a un modello di funzione (come' std :: sort'), ma non con un istanziazione di un oggetto modello di classe (come 'std :: priority_queue'). –

+0

Sarebbe meglio se avessi spiegato un po 'sul "* Perché? *". Ma grazie! – azam

2

Come indica il messaggio di errore, le funzioni non possono essere utilizzate come parametri del modello. Il priority_queue copierà un oggetto del tipo di confronto . Ad esempio, questo potrebbe essere std::less<int>, dove un oggetto di quel tipo è std::less<int>() e viene chiamato è std::less<int>()(x, y). In C++ 11, è possibile utilizzare decltype, ma in C++ 03 il modo "canonico" è creare un "functor" (un intero tipo dedicato all'utilizzo come oggetto funzione). Questo è uno dei motivi per cui lambdas sono stati creati.

+0

Bello, per individuare la mancanza di C++ e spiegare il motivo dell'avvento di 'lambda's in C++ 11. – azam

Problemi correlati