C ++: how to pass any iterative type as a parameter to a function

As an exercise, I am trying to implement the Pythons join() method in C ++. I will eventually add the function as a method of the std::string class, but I believe that making it work is rather a priority. I defined the function as follows:

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

Is there any way to guarantee that the Iterable type is actually iterable? For instance. I would not want to get int or char ..

thanks for the help

+6
source share
2 answers

In C ++, instead of having one Iterable , we pass an iterator (almost a pointer) to the beginning and end of the range:

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

Please note that sep must be passed as a reference to a constant, since you do not need to copy it.

You do not need to worry about whether the Iter actually an iterator. This is because the code simply does not compile if it does not work.

For example, suppose you implemented it like this (this is a bad implementation):

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

Then the type passed as Iter should have operator++ , operator!= And operator* , which is a well-understood iterator contract.

+5
source

All standard C ++ collections have member functions begin() and end() . You could use this fact to make sure that the passed argument is a collection (in your terminology - iterable) using SFINAE (C ++ 11 example):

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

+1
source

Source: https://habr.com/ru/post/1012398/


All Articles