Frage

Ich muss designe Prädikat für stl Algorithmen wie find_if, count_if.

namespace lib
{
    struct Finder
    {
        Finder( const std::string& name ):
            name_( name )
        {
        }

        template< typename TElement >
        bool operator( const TElement& element )
        {
            return element.isPresent( name_ );
        }

        /* template< typename TElement >
        bool operator( const TElement& element )
        {
            const Data& data = element.getData();
            return data.isPresent( name_ );
        }*/ 
    };
}

Aber ich brauche es verschiedene Betreiber zu haben () nach Anwesenheit einiger bestimmter Methoden in Telement. Wie, wenn es „getData“ Ich möchte, dass die Daten überprüfen und, wenn ich es nicht andere Aktionen tun würde.

Ich bin mir dessen bewusst SFINAE. Aber ich habe nicht boost :: an dem Projekt. Also entweder gibt es einige einfache Implementierung der Vorlage „has_method“ oder Sie kennen eine andere Design-Lösung.

Ich kann nicht bestimmte Arten zeigen und einfach Überlastung, weil ich diese Prädikats zum einen der Projektbibliothek setzen möchten, die mit „getData“ Methode über diese speziellen Klassen nicht kennen.

Lösung mit Klasseneigenschaften sind gut, soweit es kein Namensraum ist. Prädikat Finder in in „lib“ Namespace und Klasse mit „getData“ ist in „Programm“ Namespace.

Danke.

War es hilfreich?

Lösung

Warum verwenden Vorlage mathods überhaupt? Verwenden Sie einfach die spezifische Klasse, dass Sie es auf oder eine gemeinsame Basisklassen basieren soll, wenn es viele Klassentypen sind.

z.

struct Finder
{
    Finder( const std::string& name ):
        name_( name )
    {
    }

    bool operator( const IsPresentBaseClass& element )
    {
        return element.isPresent( name_ );
    }

    bool operator( const GetDataBaseClass& element )
    {
        const Data& data = element.getData();
        return data.isPresent( name_ );
    } 
 };

Wenn dieses Muster sehr viel mit verschiedenen Klassentypen geschieht und Sie kennen die Typen vor dem Prädikat verwenden Sie das Prädikat Vorlage könnten selbst.

z.

template<class T1, class T2>
struct Finder
{
    Finder( const std::string& name ):
        name_( name )
    {
    }

    bool operator( const T1& element )
    {
        return element.isPresent( name_ );
    }

    bool operator( const T2& element )
    {
        const Data& data = element.getData();
        return data.isPresent( name_ );
    } 
 };

oder ein anderer Ansatz, den Sie ist verwenden könnte irgendeine Art von Klasseneigenschaften zu verwenden, um die Informationen zu halten.

z.

struct UseIsPresent
{
    template<class T>
    static bool CompareElement( const T& element, const std::string& name )
    {
        return element.isPresent( name );
    }
};

struct UseGetData
{
    template<class T>
    static bool CompareElement( const T& element, const std::string& name )
    {
        const Data& data = element.getData();
        return data.isPresent( name );
    } 
};

// default to using the isPresent method
template <class T>
struct FinderTraits
{
    typedef UseIsPresent FinderMethodType;
};

// either list the classes that use GetData method
// or use a common base class type, e.g. UseGetData
template <>
struct FinderTraits<UseGetData>
{
    typedef UseGetData FinderMethodType;
};

struct Finder
{
    Finder( const std::string& name )
    : name_( name )
    {
    }

    template<class T>
    bool operator()( const T& element )
    {
        return FinderTraits<T>::FinderMethodType::CompareElement<T>(element, name_);
    }

    std::string name_;
};

Die Nachteile all dieser Methoden ist, dass irgendwann Sie die Typen wissen müssen in der Lage sein, sie in welche Methode aufzuteilen zu verwenden.

Andere Tipps

Sie können einen Blick auf Veldhuizen die Homepage für die switch Vorlage. Sie können sich wahrscheinlich diese verwenden, um den genauen Operator zu wählen?

Haben Sie Ihre Typen von „Funktionalität Typen“ (zB eine Art „has_function1“) ableiten, die als Java-Schnittstellen arbeiten und Sie haben eine Chance, weil SFINAE verwendet werden können, zu testen, ob ein Typ kann in eine andere umgewandelt werden.

Wenn Sie interessiert sind, ich in sie schauen und geben Sie eine ausführlichere Antwort.

EDIT: Ich weiß, Sie sagen, Sie nicht Boost-Bibliotheken zur Verfügung haben, aber gibt es alles, was Sie davon ab, die wenige Dateien zu verhindern, die nötig sind, um Auftrieb zu bekommen :: is_convertible Arbeits? Es sei nichts insbesondere zu kompilieren!

Boost ist keine Magie; SFINAE verwendet, ist recht einfach:

    template< typename TElement >
    bool operator( const TElement& element, ... )
    {
        return element.isPresent( name_ );
    }

    template< typename TElement >
    bool operator( const TElement& element, const Data& data = element.getData())
    {
        return data.isPresent( name_ );
    }

SFINAE wird die zweite Überlast entfernen, wenn sie nicht kompilieren lassen. Überladungsauflösung wird die zweite holen, wenn es da nicht kompiliert ... ist ein schlechtes Spiel.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top