基于空结束字符串循环的范围 [英] Range based for loops on null terminated strings

查看:137
本文介绍了基于空结束字符串循环的范围的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我假设基于范围的循环将支持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:


  1. 范围是数组

  2. 范围是具有可调用 begin end 方法

  3. 在关联命名空间中有ADL可访问(加上 std 命名空间) / li>
  1. The range is an array
  2. The range is a class with a callable begin and end method
  3. 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆