基于空结束字符串循环的范围 [英] Range based for loops on null terminated strings
问题描述
我假设基于范围的循环将支持C风格的字符串。
I sort of assumed that range based for loops would support C-style strings
void print_C_str(const char* str)
{
for(char c : str)
{
cout << c;
}
}
但是不是这样,标准 [stmt.ranged](6.5.4)
说基于范围的工作在以下三种可能性之一:
However this is not the case, the standard [stmt.ranged] (6.5.4)
says that range-based-for works in one of 3 possibilities:
- 范围是数组
- 范围是具有可调用
begin
和end
方法 - 在关联命名空间中有ADL可访问(加上
std
命名空间) / li>
- The range is an array
- The range is a class with a callable
begin
andend
method - There is ADL reachable in an associated namespace (plus the
std
namespace)
当我添加开始
和结束
在全局命名空间中的 const char *
函数我仍然得到错误(从VS12和GCC 4.7)。
When I add begin
and end
functions for const char*
in the global namespace I still get errors (from both VS12 and GCC 4.7).
有没有办法获得基于范围的for循环使用C风格字符串?
Is there a way to get range-based-for loops to work with C style strings?
我尝试向命名空间std
添加一个重载,这个工作,但是我的理解是添加重载到 namespace std
I tried adding an overload to namespace std
and this worked but to my understanding it's illegal to add overloads to namespace std
(is this correct?)
推荐答案
迭代器对于以null结束的字符串,你可以通过调用返回特殊范围的指针上的函数来实现,而不是将指针本身当作范围。
If you write a trivial iterator for null-terminated strings, you can do this by calling a function on the pointer that returns a special range, instead of treating the pointer itself as the range.
template <typename Char>
struct null_terminated_range_iterator {
public:
// make an end iterator
null_terminated_range_iterator() : ptr(nullptr) {}
// make a non-end iterator (well, unless you pass nullptr ;)
null_terminated_range_iterator(Char* ptr) : ptr(ptr) {}
// blah blah trivial iterator stuff that delegates to the ptr
bool operator==(null_terminated_range_iterator const& that) const {
// iterators are equal if they point to the same location
return ptr == that.ptr
// or if they are both end iterators
|| is_end() && that.is_end();
}
private:
bool is_end() {
// end iterators can be created by the default ctor
return !ptr
// or by advancing until a null character
|| !*ptr;
}
Char* ptr;
}
template <typename Char>
using null_terminated_range = boost::iterator_range<null_terminated_range_iterator<Char>>;
// ... or any other class that aggregates two iterators
// to provide them as begin() and end()
// turn a pointer into a null-terminated range
template <typename Char>
null_terminated_range<Char> null_terminated_string(Char* str) {
return null_terminated_range<Char>(str, {});
}
并且使用方式如下:
for(char c : null_terminated_string(str))
{
cout << c;
}
我不认为这会失去任何表现力。其实,我觉得这个更清晰。
I don't think this loses any expressiveness. Actually, I think this one is clearer.
这篇关于基于空结束字符串循环的范围的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!