基于对空终止字符串环路范围(Range based for loops on null termin

2019-07-18 14:08发布

我有点假设为基础的循环将支持C风格的字符串范围

void print_C_str(const char* str)
{
    for(char c : str)
    {
        cout << c;
    }
}

然而,这不是这种情况,该标准[stmt.ranged] (6.5.4)表示,范围为基础的换在3种可能性之一工作:

  1. 范围是一个数组
  2. 的范围是与一个可调用一类beginend的方法
  3. 有ADL可达在相关命名空间(加上std命名空间)

当我添加beginend的功能const char*全局命名空间我仍然得到错误(来自VS12和GCC 4.7)。

有没有办法让范围为基础,对循环使用C风格的字符串工作吗?

我尝试添加的过载namespace std和这个工作,但我的理解是违法添加的过载到namespace std (这是正确的?)

Answer 1:

如果你写null结尾的字符串一个平凡的迭代器,你可以通过调用返回一个特殊的范围内,指针的函数,而不是治疗指针本身的范围内做到这一点。

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

我不认为这将失去任何表现。 其实,我觉得这是一个更加清晰。



Answer 2:

A C-string是不是一个数组,它不具有类begin / end成员,因为该参数是一个原始的,你将不会被ADL发现任何东西。 按理说,这应该是纯不合格查找,与ADL,它发现在全局命名空间的功能。 但是,考虑措辞,我想这是不可能的。



Answer 3:

一个可能的解决方法是包裹空在另一种类型的终止字符串。 最简单的实现如下(比是少高性能R.费尔南德斯Martinho的建议,因为它会调用strlen ,但它也是显著更少的代码)。

class null_terminated_range {
    const char* p:
public:
    null_terminated_range(const char* p) : p(p) {}
    const char * begin() const { return p; }
    const char * end() const { return p + strlen(p); }
};

用法:

for(char c : null_terminated_range(str) ) 


文章来源: Range based for loops on null terminated strings