2016-12-24 2 views
0
#include <iostream> 
#include <algorithm> 
#include <numeric> 
#include <vector> 
using namespace std; 

class C 
{ 
public: 
    vector<int> CSort(); 
    bool Func(int x, int y); 
private: 
    vector<int> data; 
}; 

vector<int> C::CSort() 
{ 
    vector<int> result(data.size(), 0); 
    iota(result.begin(), result.end(), 0); 
    sort(result.begin(), result.end(), Func); 
    return result; 
} 

bool C::Func(int x, int y) 
{ 
    return (data[x] > data[y]); 
} 

Dans ma classe C défini comme ci-dessus, je voudrais obtenir un vecteur d'ordre de data avec std::sort en utilisant la fonction de membre Func. Le résultat était une erreurQuelle est la bonne façon de référencer une fonction membre d'une classe?

'C :: Func': syntaxe non standard; utilisation & 'pour créer un pointeur vers un membre

Je crois que cela a quelque chose à voir avec Why doesn't reference-to-member exist in C++.

Cependant, je ne peux pas trouver un moyen correct de faire référence à cette fonction dans std::sort. Comment puis-je l'implémenter correctement?

+0

@ArchbishopOfBanterbury Vous aviez raison, et initialiser un vecteur d'ordre décroissant est un bon rappel, merci beaucoup;) –

+0

Comme un côté notez, 'std :: sort (result, & C :: Func);' devrait fonctionner dès le début avec les prochaines Ranges TS. – Morwenn

Répondre

0

Façon rapide et sale: déplacez Func en dehors de la classe.

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

class C 
{ 
public: 
    vector<int> CSort(); 
private: 
    vector<int> data; 
}; 

bool Func(int x, int y) { 
    return x > y; 
} 

vector<int> C::CSort() 
{ 
    vector<int> result(data.size(), 0); 
    // iota(data.begin(), data.end(), 0); 
    sort(data.begin(), data.end(), Func); 
    return result; 
} 
+0

Downvote pourquoi? C++ ** n'autorise pas ** la référence à la fonction de membre non statique. – gongzhitaao

+0

Il ne répond pas directement à la question, mais je ne pense pas qu'il mérite une downvote. (Surtout pas sans quelques explications) – wally

+0

@gongzhitaao Je crois avoir fait une erreur dans mon code. Désolé pour le problème de communication. –

1

lambda fonctionne:

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

class C 
{ 
public: 
    vector<int> CSort(); 
    bool Func(int x, int y); 
private: 
    vector<int> data; 
}; 

vector<int> C::CSort() 
{ 
    vector<int> result(data.size(), 0); 
    iota(data.begin(), data.end(), 0); 
    sort(data.begin(), data.end(), [this](auto& l, auto& r) {return Func(l, r); }); 
    return result; 
} 

bool C::Func(int x, int y) 
{ 
    return (data[x] > data[y]); 
} 

int main() 
{ 
    C c; 
} 

ou bind:

#include <iostream> 
#include <algorithm> 
#include <numeric> 
#include <vector> 
#include <functional> 

using namespace std; 

class C 
{ 
public: 
    vector<int> CSort(); 
    bool Func(int x, int y); 
private: 
    vector<int> data; 
}; 

vector<int> C::CSort() 
{ 
    vector<int> result(data.size(), 0); 
    iota(data.begin(), data.end(), 0); 
    sort(data.begin(), data.end(), std::bind(&C::Func,this,std::placeholders::_1,std::placeholders::_2)); 
    return result; 
} 

bool C::Func(int x, int y) 
{ 
    return (data[x] > data[y]); 
} 

int main() 
{ 
    C c; 
} 
+1

n'utilisez pas 'std :: bind' pour les fonctions membres tant que vous n'avez pas saisi la fonction via [' std :: mem_fn'] (http://en.cppreference.com/w/cpp/utility/functional/ mem_fn) mais pour être honnête les deux sont inutiles en C++ 14 – Mgetz

+0

@Mgetz Intéressant. Mais comment cela fonctionnerait-il? N'avons-nous pas besoin de nous lier à une instance spécifique dans cet exemple? – wally

+1

Nous le faisons, mais en C++, le moyen le plus sûr de récupérer une référence à une fonction membre est d'utiliser 'std :: mem_fn', c'est aussi un moyen facile. L'objet fonction retourné est garanti avoir le paramètre 'this' comme premier paramètre. Considérant qu'une fonction pointeur-à-membre comme vous utilisez n'est pas comme c'est un détail d'implémentation spécifique ABI. – Mgetz

1

Vous avez deux options:

Si vous n'avez pas accès à C++ 11 vous pouvez aller à l'ancienne école et mettre en œuvre votre propre comparateur qui préserve l'état:

class C 
{ 
    friend struct MyComp; 
public: 
    vector<int> CSort(); 
private: 
    vector<int> data; 
}; 

struct MyComp 
{ 
    C* data; 
    MyComp(C* data) : data(data) {} 
    bool operator()(int x, int y) 
    { 
     return data->data[x] > data->data[y]; 
    } 
}; 

vector<int> C::CSort() 
{ 
    vector<int> result(data.size(), 0); 
    iota(data.begin(), data.end(), 0); 
    sort(data.begin(), data.end(), MyComp(this)); 
    return result; 
} 

Cependant, si vous le faites, vous pouvez simplement utiliser un lambda:

vector<int> C::CSort() 
{ 
    vector<int> result(data.size(), 0); 
    iota(data.begin(), data.end(), 0); 
    sort(data.begin(), data.end(), [this] (int x, int y) { 
     return (data[x] > data[y]); 
    }); 
    return result; 
}