2016-11-17 2 views
6

Als Übung versuche ich Pythons join() Methode in C++ zu implementieren. Ich werde schließlich die Funktion als eine Methode der std::string Klasse hinzufügen, aber ich denke, es zu arbeiten ist mehr eine Priorität. Ich habe die Funktion wie folgt definiert:C++: Wie man einen iterierbaren Typ als Funktionsparameter übergibt

template<typename Iterable> 
std::string join(const std::string sep, Iterable iter); 

Gibt es eine Möglichkeit, dass ich sicherstellen kann, dass der Iterable Typ ist iterable eigentlich? Z.B. Ich möchte nicht eine int oder char ..

Danke für Ihre Hilfe

+2

Wie würden Sie definieren "iterierbar"? – Galik

+0

@Galik Ich würde es als Container definieren, die Sie durchlaufen können – aydow

+0

Können Sie ein echtes Beispiel, wie Sie diese Funktion aufrufen? – Galik

Antwort

5

In C++ erhalten, anstatt eine Iterable hat, gehen wir in einem Iterator (fast ein Zeiger) auf der Vorderseite und dem Ende des Bereichs:

template<typename Iter> 
std::string join(const std::string &sep, Iter begin, Iter end); 

Beachten Sie, dass die sep sollte als const Referenz geben werden, wie man es nicht kopieren müssen.

Sie müssen sich keine Gedanken darüber machen, ob der Iter tatsächlich ein Iterator ist. Dies liegt daran, dass der Code einfach nicht kompiliert wird, wenn er nicht funktioniert.

Beispiel: Angenommen, Sie es wie so umgesetzt (dies ist eine schlechte Implementierung):

template<typename Iter> 
std::string join(const std::string &sep, Iter begin, Iter end) { 
    std::string result; 

    while (begin != end) { 
     result += *begin; 
     ++begin; 
     if (begin != end) result += sep; 
    } 

    return result; 
} 

Dann wird der Typ als Iter übergeben muss eine operator++ haben, ein operator!= und ein operator* zu arbeiten, die ist der gut verstandene Vertrag eines Iterators.

+1

"(fast ein Zeiger)" .. technisch könnte es ein Zeiger sein, z.B. 'char * x =" Hallo "; join ("", x, x + 5); " – txtechhelp

+0

das ist mir eingefallen, aber Pythonsyntax ist' "string" .join (liste) 'so versuche ich das nachzuahmen. Ich wüsste, dass es im Widerspruch zu C++ style – aydow

+0

auch, können Sie erklären, warum es eine schlechte Umsetzung ist? – aydow

1

Alle Standard-C++ - Auflistungen haben begin() und end() Mitgliedsfunktionen. Sie könnten die Verwendung dieser Tatsache machen, um sicherzustellen, dass das übergebene Argument ist eigentlich eine Sammlung (in der Terminologie - iterable) von einigen SFINAE (C++ 11 Beispiel):

#include <array> 
#include <list> 
#include <vector> 
#include <map> 
#include <string> 

template <class Iterable> 
auto join(const std::string sep, const Iterable& iterable) -> decltype(iterable.begin(), iterable.end(), std::string{}) { 
    (void)sep; // to suppress warning that sep isn't used 
    // some implementation 
    return {}; 
} 

int main() { 
    join(";", std::array<int, 5>{}); 
    join(";", std::list<int>{}); 
    join(";", std::vector<float>{}); 
    join(";", std::string{}); 
    join(";", std::map<int, float>{}); 
    //join(";", int{}); // does not compile as int is not a collection 
} 

[live demo]

Verwandte Themen