2016-11-17 47 views
6

作爲一個練習,我試圖在C++中實現Pythons join()方法。我最終將該功能作爲std::string類的一種方法添加,但我認爲讓它起作用更重要。我已經定義瞭如下函數:C++:如何通過任何可迭代類型作爲函數參數

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

有什麼辦法可以確保Iterable類型實際上是可迭代的嗎?例如。我不希望收到intchar ..

感謝您的幫助

+2

你如何定義「迭代」? – Galik

+0

@Galik我將它定義爲容器,你可以迭代通過 – aydow

+0

你能提供一個真實的例子顯示你將如何調用這個函數? – Galik

回答

5

在C++中,而不是一個Iterable,我們傳遞一個迭代器(幾乎指針)的前部和結束範圍:

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

注意,sep應該爲const 參考傳遞,因爲你並不需要複製。

不過你不需要擔心Iter是否實際上是一個迭代器。這是因爲如果代碼不起作用,代碼將無法編譯。

例如,假設你實現它像這樣(這是一個糟糕的實現):

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; 
} 

然後傳遞進來Iter類型必須有一個operator++,一個operator!=operator*工作,這是一個迭代器很好理解的合約。

+1

「(幾乎是一個指針)」..在技術上它可以是一個指針,例如, 'char * x =「hello」;加入(「」,x,x + 5);' – txtechhelp

+0

已經發生在我身上,但pythons的語法是''string「.join(list)'所以我試圖模仿它。我不知道它也與C++風格 – aydow

+0

衝突,你能解釋爲什麼它是一個糟糕的實現嗎? – aydow

1

所有標準C++集合都有begin()end()成員函數。你可以利用這一事實,以確保傳遞的參數實際上是一個集合(在您的術語 - 迭代器)一些SFINAE(C++ 11例):

#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]

相關問題