2012-04-09 2 views
4

Existe-t-il des objets fonction dans le boost qui sont des équivalents génériques de la famille d'objets std :: equal_to, std :: greater etc.?Équivalent générique aux objets de fonction std

Essentiellement, std :: equal_to devrait devenir quelque chose comme

struct generic_equal_to 
{ 
    template <class T, class U> 
    bool operator()(const T& t, const U& u) const 
    { 
     return t == u; 
    } 
}; 

Je peux voir comment les versions génériques de std :: etc., plus peut-être plus délicat en raison de problèmes avec le type de retour (si le decltype peut résoudre cela). Je ne vois pas pourquoi l'objet std :: equal_to function lui-même devrait avoir besoin d'un argument template.

Sûrement quelque part dans boost ou dans la STL ces versions existent? Ils sont, bien sûr, triviaux à écrire, mais je n'aime pas trop reproduire le code de la bibliothèque, en particulier pour quelque chose d'aussi trivial que celui-ci.

EDIT:

Comme un contexte à pourquoi je voudrais au lieu d'utiliser lambdas, ou une autre méthode de génération fonction objet:

je en train d'écrire une fonction de comparaison de séquences boost::fusion générique ainsi:

template <class T> 
bool sequence_equal(const T& left, const T& right) 
{ 
    return fusion::all(
     fusion::zip(left, right), 
     fusion::fused<generic_equal_to>()); 
} 

Notez la partie fusion::fused<generic_equal_to>, ce qui conduit à l'isse que vous ne pouvez pas spécifier pratiquement un boost::lambda ou boost::phoenix fonction-objet par type. Je suppose qu'une solution pourrait être decltype:

fusion::fused<decltype(_1 == _2)>() 

Cela semble très difficile cependant, et pourrait ne pas fonctionner même, selon la façon dont boost::lambda ou boost::phoenix est mis en œuvre - Je ne suis vraiment pas sûr.

Je sais que vous pouvez utiliser fusion::make_fused pour contourner tout ce problème, mais vous devez ensuite instancier l'objet fonction. La solution que je pensais, alors, serait un non-modèle equal_to struct - j'ai appelé le mien generic_equal_to.

Je sais que c'est un problème très trivial - après tout, make_fused(_1 == _2) va probablement s'incorporer à peu près le même assemblage que fused<generic_equal_to>. Je ne pouvais pas croire qu'il n'y avait pas d'objet fonction generic_equal_to dans boost ou dans la STL n'importe où, d'où cette question.

+2

Je pense que vous voulez dire '' –

+1

+1 opérateur() (const T & T, U const & u), mais je ne pense pas que vous trouverez celui qui est pris en charge. Le problème est important (je viens d'écrire ce même code dans [une réponse] (http://stackoverflow.com/questions/10063037/unordered-set-storing-elements-as-pointers/10063081#10063081) hier, mais c'est pas assez sexy pour attirer les développeurs de Boost, et 'std :: equal_to' n'est pas assez cassé pour que le comité de standardisation le déprécie. – Potatoswatter

+0

@ AndrewTomazos-Fathomling hah yep! Essayer d'écrire du code sans ordinateur pour vérifier ma syntaxe * toujours * me fait remonter quelque part – Ayjay

Répondre

1

Je ne pense pas qu'il y ait quelque chose d'aussi direct que ce que vous demandez, mais il y a des utilitaires qui couvrent non seulement vos cas d'utilisation, mais vont au-delà. Ils sont Boost.Lambda et Boost.Phoenix (ce dernier étant un successeur plus générique de la bibliothèque lambda).

Exemple d'utilisation Boost.Lambda pour l'égalité générique:

#include <boost/lambda/lambda.hpp> 
#include <iomanip> 
#include <iostream> 

struct foo {}; 

bool operator==(foo, foo) { return true; } 
bool operator==(foo, int) { return false; } 

template <typename T, typename U, typename Func> 
void f(const T& x, const U& y, Func func) 
{ 
    std::cout << func(x, y) << std::endl; 
} 

int main() 
{ 
    using namespace boost::lambda; // for placeholders 
    std::cout << std::boolalpha; 

    foo a, b; 
    int i = 0; 

    f(a, b, _1 == _2); 
    f(a, i, _1 == _2); 
} 

Et même, avec Phoenix:

#include <boost/phoenix.hpp> 
#include <iomanip> 
#include <iostream> 

struct foo {}; 

bool operator==(foo, foo) { return true; } 
bool operator==(foo, int) { return false; } 

template <typename T, typename U, typename Func> 
void f(const T& x, const U& y, Func func) 
{ 
    std::cout << func(x, y) << std::endl; 
} 

int main() 
{ 
    using namespace boost::phoenix::arg_names; // for placeholders 
    std::cout << std::boolalpha; 

    foo a, b; 
    int i = 0; 

    f(a, b, arg1 == arg2); 
    f(a, i, arg1 == arg2); 
} 

Chacun d'eux peut être étendu pour supporter les autres opérateurs de la manière évidente (et plus généralement, dans d'autres expressions). Je voudrais personnellement aller avec Phoenix, parce que si vous découvrez que vous avez besoin de plus de fonctionnalités que les offres lambda, vous ne finirez pas y compris les deux.

+0

Ouais, je suis conscient des autres façons de générer des objets fonction, mais le but de ma question était de savoir si les opérations triviales étaient déjà définies quelque part . Ils le sont, mais ils sont tous modélisés sur le 'struct' au lieu de sur le' operator() '. – Ayjay

+0

J'ai juste ajouté une raison pour expliquer pourquoi j'étais réticent à utiliser 'boost :: lambda' ou' boost :: phoenix'. – Ayjay

+0

@Ayjay: Utilisez simplement 'make_fused'. Ils n'implémenteraient pas manuellement les trucs stdlib s'ils ont déjà des utilitaires qui en font plus. – GManNickG

0

Maintenant en C++ 14 il y a std::equal_to<void> (qui peut également être utilisé comme std::equal_to<>)

std::equal_to<> est une spécialisation de std::equal_to avec le paramètre et le type de retour déduit.

template< class T, class U> 
constexpr auto operator()(T&& lhs, U&& rhs) const 
    -> decltype(std::forward<T>(lhs) == std::forward<U>(rhs)); 

Renvoie le résultat de la comparaison de l'égalité entre les LHS et RHS.

Docs

Questions connexes