2013-03-25 20 views
5

Vorrei utilizzare diverse strategie per ordinare un vettore. Ma non riesco a capire come passare un funtore figlio e usarlo in std::sort in seguito. Ogni volta che uso la classe astratta per la strategia di ordinamento, finisco con l'errore cannot allocate an object of abstract type. C'è un modo per utilizzare i functors ereditati come argomenti std::sort? Grazie!std :: sort utilizzando il functor ereditato

#include <iostream> 
#include <vector> 
#include <algorithm> 
using namespace std; 


class BaseSort{ 
public: 
    virtual ~BaseSort() {}; 
    virtual bool operator()(const int& a, const int& b) = 0; 
}; 

class Asc : public BaseSort{ 
public: 
    bool operator()(const int& a, const int& b){ 
     return a < b; 
    } 
}; 

class Desc : public BaseSort{ 
public: 
    bool operator()(const int& a, const int& b){ 
     return a > b; 
    } 
}; 

void print(const vector<int>& values) { 
    for (unsigned i = 0; i < values.size(); ++i) { 
     cout << values[i] << ' '; 
    } 
    cout << endl; 
} 

int main() { 
    vector<int> values = {2,1,3}; 
    sort(values.begin(), values.end(), Asc()); // {1,2,3} 
    print(values); 
    sort(values.begin(), values.end(), Desc()); // {3,2,1} 
    print(values); 
    Asc* asc = new Asc(); 
    sort(values.begin(), values.end(), *asc); // {1,2,3} 
    print(values); 
    BaseSort* sortStrategy = new Desc(); 
    sort(values.begin(), values.end(), *sortStrategy); //cannot allocate an object of abstract type ‘BaseSort’ 
    print(values); 
    return 0; 
} 
+1

non collegati, ma operatore la funzione del comparatore dovrebbe essere 'const'. Cioè 'virtual bool operator() (const int & a, const int & b) const = 0;' – WhozCraig

risposta

9

Devi usare std::ref(), altrimenti l'argomento sarà passato per valore (provocando un tentativo di copiare-costruire un oggetto di tipo BaseSort, che è illegale poiché BaseSort è astratta - e anche se non fosse, si otterrebbe affettare):

sort(values.begin(), values.end(), std::ref(*sortStrategy)); 
//         ^^^^^^^^ 
+0

@DrewDormann: Grazie per la correzione :) –

+1

'cppreference' dice che' std :: ref' è solo C++ 11 - in che modo le persone hanno affrontato questo problema prima di avere 'std :: ref'? – us2012

+1

@ us2012: Boost ha un 'boost :: ref' e' boost :: cref' se ricordo male –