2016-06-20 7 views
4

Ich habe eine Reihe von boost :: shared_ptr, die ich nicht durch die geteilten Zeiger, sondern durch die Zeichenfolgen geordnet und uniqued werden möchte. Muss ich eine neue Vergleichsfunktion zur Verfügung stellen, um gemeinsame Zeiger zu erhalten und den Inhalt zu vergleichen, oder gibt es einen solchen Vergleicher, den ich benutzen kann?Std Set von boost :: shared_ptr <string>

Antwort

5

Das ist ziemlich spezifisch, so dass Sie wahrscheinlich einen benutzerdefinierten Komparator benötigen.

sollte diese Arbeit:

struct pointercompare 
{ 
    bool operator()(const boost::shared_ptr<std::string>& a, const boost::shared_ptr<std::string>& b) 
    { 
     return (*a)>(*b); 
    } 
} 
1

ich eine allgemeine Art und Weise schreiben würde, Prädikate und Iteratoren von Einwickeln, die Wert-Semantik auf jeden Zeiger artigen Besitzer zuordnet.

Dies wird dann völlig allgemein und wiederverwendbar.

Einfache Version hier

Bonus Code unten führt eine komplette Bibliothek für diese Art der Sache

#include <utility> 
#include <boost/shared_ptr.hpp> 
#include <vector> 
#include <algorithm> 

template<class Comp> 
struct pointee 
{ 
    pointee(Comp comp = Comp()) : _comp(comp) {} 

    template<class APtr, class BPtr> 
    bool operator()(const APtr& a, const BPtr& b) 
    { 
     return _comp(*a, *b); 
    } 

    Comp _comp; 
}; 



int main() 
{ 
    std::vector<boost::shared_ptr<int>> v; 

    std::sort(v.begin(), v.end(), pointee<std::less<>>()); 
    std::sort(v.begin(), v.end(), pointee<std::greater<>>()); 

} 

Für Bonuspunkte ...

#include <utility> 
#include <boost/shared_ptr.hpp> 
#include <vector> 
#include <algorithm> 
#include <functional> 


template<class T, class X, class Y> 
struct is_binary_op 
{ 
    template<class U> static auto test(U* p) -> decltype((*p)(std::declval<X>(), std::declval<Y>()), void(), std::true_type()); 
    template<class U> static auto test(...) -> decltype(std::false_type()); 

    static constexpr bool value = decltype(test((T*)0))::value; 
}; 

template<class T, class X, class Y> static constexpr bool IsBinaryOp = is_binary_op<T, X, Y>::value; 

template<class T, class X> 
struct is_unary_op 
{ 
    template<class U> static auto test(U* p) -> decltype((*p)(std::declval<X>()), void(), std::true_type()); 
    template<class U> static auto test(...) -> decltype(std::false_type()); 

    static constexpr bool value = decltype(test((T*)0))::value; 
}; 
template<class T, class X> static constexpr bool IsUnaryOp = is_unary_op<T, X>::value; 

namespace detail { 
    template<class Comp> 
    struct pointee 
    { 
     pointee(Comp comp = Comp()) : _comp(comp) {} 

     template< 
     class APtr, 
     class BPtr 
     > 
     auto operator()(const APtr& a, const BPtr& b) const 
     -> std::enable_if_t< 
     IsBinaryOp<Comp, decltype(*a), decltype(*b)> 
     , bool> 
     { 
      return _comp(*a, *b); 
     } 

     template< 
     class APtr 
     > 
     auto operator()(const APtr& a) const 
     -> std::enable_if_t< 
     IsUnaryOp<Comp, decltype(*a)> 
     , bool> 
     { 
      return _comp(*a); 
     } 

     Comp _comp; 
    }; 

    template<class Iter> 
    struct deref_iter : Iter 
    { 
     deref_iter(Iter iter) : Iter(iter) {} 

     auto& operator*() const { 
      return **static_cast<const Iter&>(*this); 
     } 
    }; 
} 

template<class Pred> 
auto pointee(Pred&& pred) 
{ 
    return detail::pointee<std::decay_t<Pred>>(std::forward<Pred>(pred)); 
} 

template<class Iter> 
auto deref_pointee(Iter&& iter) 
{ 
    return detail::deref_iter<std::decay_t<Iter>>(std::forward<Iter>(iter)); 
} 


int main() 
{ 
    std::vector<boost::shared_ptr<int>> v; 

    // sort using the less predicate on the pointee 
    std::sort(v.begin(), v.end(), pointee(std::less<>())); 

    // sort using the greater predicate on the pointee 
    std::sort(v.begin(), v.end(), pointee(std::greater<>())); 

    // apply a unary predicate to every pointee 
    std::for_each(v.begin(), v.end(), pointee(std::logical_not<>())); 

    // transform the pointees by binding a binary predicate to a value and 
    // turning it into a unary predicate that adds 6 
    std::transform(v.begin(), v.end(), 
        deref_pointee(v.begin()), 
        pointee(std::bind(std::plus<>(), 6, std::placeholders::_1))); 

} 
Verwandte Themen