9

<algorithm>头提供std::equal_range(),以及一些将其作为成员函数的容器。这个函数困扰我的是它返回一对迭代器,使得从开始迭代器迭代到结束迭代器变得乏味。我希望能够使用std::begin()std::end()这样我就可以使用基于 C++11 范围的 for 循环。

现在,我听说了关于专业化std::begin()和的矛盾信息std::end()- 我被告知将任何内容添加到 std 命名空间会导致未定义的行为,而我也被告知您可以提供自己的专业化std::begin()and std::end()

这就是我现在正在做的事情:

namespace std
{
    template<typename Iter, typename = typename iterator_traits<Iter>::iterator_category>
    Iter begin(pair<Iter, Iter> const &p)
    {
        return p.first;
    }
    template<typename Iter, typename = typename iterator_traits<Iter>::iterator_category>
    Iter end(pair<Iter, Iter> const &p)
    {
        return p.second;
    }
}

这确实有效:http: //ideone.com/wHVfkh

但我想知道,这样做有什么缺点?有一个更好的方法吗?

4

1 回答 1

7

17.6.4.2.1/1除非另有说明,否则如果 C++ 程序向命名空间std或命名空间内的命名空间添加声明或定义,则其行为未定义。只有当声明依赖于用户定义的类型并且特化满足原始模板的标准库要求并且没有明确禁止时,std程序才能将任何标准库模板的模板特化添加到命名空间 。std

所以是的,我相信,从技术上讲,您的代码表现出未定义的行为。也许您可以编写一个简单的类,在其构造函数中使用一对迭代器,并实现begin()end()方法。然后你可以写类似

for (const auto& elem: as_range(equal_range(...))) {}
于 2013-10-11T21:09:09.723 回答