ayd*_*dow 7 c++ iterable generic-type-argument
作为练习,我正在尝试join()用C++ 实现Python的方法.我最终会将该函数添加为std::string类的方法,但我认为让它工作更为重要.我已经定义了如下函数:
template<typename Iterable>
std::string join(const std::string sep, Iterable iter);
Run Code Online (Sandbox Code Playgroud)
有什么方法可以确保Iterable类型实际上是可迭代的吗?例如,我不想收到int或char..
在C++中,Iterable我们将迭代器(几乎是一个指针)传递给范围的前端和末端,而不是一个迭代器:
template<typename Iter>
std::string join(const std::string &sep, Iter begin, Iter end);
Run Code Online (Sandbox Code Playgroud)
请注意,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;
}
Run Code Online (Sandbox Code Playgroud)
然后传入的类型Iter必须有一个operator++,一个operator!=和一个operator*工作,这是一个很好理解的迭代器契约.
所有标准的 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
}
Run Code Online (Sandbox Code Playgroud)