Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/131.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 为什么从C++;11?_C++_Foreach_C++11_Range_Std Pair - Fatal编程技术网

C++ 为什么从C++;11?

C++ 为什么从C++;11?,c++,foreach,c++11,range,std-pair,C++,Foreach,C++11,Range,Std Pair,我刚刚发现,在某一点上,C++11草案为std::pair提供了std::begin/std::end重载,允许将一对迭代器视为适合在基于范围的for循环中使用的范围(N3126,第20.3.5.5节),但这已经被删除 有人知道它为什么被移除吗 我发现删除非常不幸,因为似乎没有其他方法可以将一对迭代器视为一个范围。事实上: 在基于范围的for循环中,begin/end的查找规则表示begin/end在1)中作为范围对象的成员函数查找,在2)中作为“关联名称空间”中的自由函数查找 std::pa

我刚刚发现,在某一点上,C++11草案为
std::pair
提供了
std::begin
/
std::end
重载,允许将一对迭代器视为适合在基于范围的for循环中使用的范围(N3126,第20.3.5.5节),但这已经被删除

有人知道它为什么被移除吗

我发现删除非常不幸,因为似乎没有其他方法可以将一对迭代器视为一个范围。事实上:

  • 在基于范围的for循环中,begin/end的查找规则表示begin/end在1)中作为范围对象的成员函数查找,在2)中作为“关联名称空间”中的自由函数查找
  • std::pair
    没有开始/结束成员函数
  • 通常,
    std::pair
    的唯一关联名称空间是名称空间std
  • 我们不允许为
    std::pair
    自己过载
    std::begin
    /
    std::end
  • 对于
    std::pair
    ,我们不能专门化
    std::begin
    /
    std::end
    (因为专门化必须是部分的,这不允许用于函数)
还有什么我遗漏的吗?

我想艾莉斯代尔·梅雷迪斯2009年的论文至少是答案的一部分。基本上,许多算法返回的迭代器对实际上不能保证为有效范围。出于这个原因,他们似乎从for range循环中删除了对
pair
的支持。然而,拟议的解决办法尚未得到充分采纳

如果您确实知道某些迭代器对确实表示有效范围,则可以将它们包装成一个自定义类型,该类型提供begin()/end()成员函数:

template<class Iter>
struct iter_pair_range : std::pair<Iter,Iter> {
    iter_pair_range(std::pair<Iter,Iter> const& x)
    : std::pair<Iter,Iter>(x)
    {}
    Iter begin() const {return this->first;}
    Iter end()   const {return this->second;}
};

template<class Iter>
inline iter_pair_range<Iter> as_range(std::pair<Iter,Iter> const& x)
{ return iter_pair_range<Iter>(x); }

int main() {
    multimap<int,int> mm;
    ...
    for (auto& p : as_range(mm.equal_range(42))) {
       ...
    }
}
模板
结构iter\u对范围:std::pair{
iter成对范围(标准:成对常数和x)
:std::对(x)
{}
Iter begin()常量{返回this->first;}
Iter end()常量{返回此->秒;}
};
模板
内联iter\u pair\u range as\u range(标准::pair const&x)
{返回iter_对_范围(x);}
int main(){
多重映射mm;
...
用于(自动和p:as_范围(mm.相等_范围(42))){
...
}
}
(未经测试)


我同意这有点尖锐。返回有效范围(如equal_range)的函数应该使用适当的返回类型这样说。有点尴尬的是,我们必须通过上面的
as\u range
之类的方式手动确认这一点。

使用c++11优化扩展上述答案:

#include <utility>

template<class Iter>
struct range_t : public std::pair<Iter, Iter> {
    using pair_t = std::pair<Iter, Iter>;
    range_t(pair_t&& src)
    : std::pair<Iter, Iter>(std::forward<pair_t>(src))
    {}

    using std::pair<Iter, Iter>::first;
    using std::pair<Iter, Iter>::second;

    Iter begin() const { return first; }
    Iter end() const { return second; }
};

template<class Iter>
range_t<Iter> range(std::pair<Iter, Iter> p) {
    return range_t<Iter>(std::move(p));
}

template<class Iter>
range_t<Iter> range(Iter i1, Iter i2) {
    return range_t<Iter>(std::make_pair(std::move(i1), std::move(i2)));
}


// TEST: 

#include <iostream>
#include <set>
using namespace std;

int main() {

    multiset<int> mySet { 6,4,5,5,5,3,3,67,8,89,7,5,45,4,3 };

    cout << "similar elements: ";
    for (const auto&i : range(mySet.lower_bound(5), mySet.upper_bound(10))) {
        cout << i << ",";
    }
    cout << "\n";

    int count = 0, sum = 0;
    for (const auto& i: range(mySet.equal_range(5)))
    {
        ++count;
        sum += i;
    }
    cout << "5 appears " << count << " times\n"
    << "the sum is " << sum << "\n";

return 0;
}
#包括
模板
结构范围\u t:public std::pair{
使用pair_t=std::pair;
范围(配对和src)
:std::pair(std::forward(src))
{}
使用std::pair::first;
使用std::pair::second;
Iter begin()常量{return first;}
Iter end()常量{return second;}
};
模板
范围\u t范围(标准::对p){
返回范围t(std::move(p));
}
模板
范围(Iter i1、Iter i2){
返回范围(std::make_pair(std::move(i1),std::move(i2));
}
//测试:
#包括
#包括
使用名称空间std;
int main(){
多集mySet{6,4,5,5,5,3,3,67,8,89,7,5,45,4,3};

cout您可以使用
boost::make\u iterator\u range
。 它用
begin()
end()
方法构造一个迭代器范围。
boost::make_iterator_range
可以接受
std::pair
的迭代器。

std::pair的begin()、end()与.first和.second不是一回事吗?@Himadri:是的,但是要在基于范围的for循环中使用它,我们需要begin()和end()。可能是因为语义(一对并不一定是一个范围)为了避免歧义,例如:boost::range就是这样做的。最好使用boost;:range而不是手写的东西。[1]:Meredith只识别了5个受此问题影响的库函数。让这些函数保证有效范围,而不是扩展类型系统,对它们来说不是更容易吗?我不太确定这种新类型是如何解决任何问题的;您仍然可以创建一个实例,其中的迭代器不能使d范围。@BenCollins:我认为主要的问题是有很多现有的应用程序代码将pair用于其他目的(考虑到迭代器的短暂性质,这可能是不寻常的,但您可以想象迭代器到迭代器的映射,例如)。为迭代器范围定义一个单独的类型可以使其用途明确,并保证现有应用程序代码不会产生任何意外的副作用。
boost::make_iterator_range
对您的作用与此相同。我理解此代码仅用于说明。效果非常好,minor quibble-posix保留此帖子修复
\u t
。请参阅:。从链接的答案中-“一些附加的标识符名称类是为C语言或POSIX.1环境的未来扩展保留的。虽然现在将这些名称用于您自己的目的可能不会导致问题,但它们确实会增加与C或POSIX标准的未来版本冲突的可能性,因此您应该避免使用这些名称。"所以,仅仅因为你使用它是一种类型,并不妨碍未来可能发生冲突。事实上,POSIX声称所有的标识符都是用“代码”>t</Cube>,所以,POSIX认为自己是自由的,现在或者在将来的任何时候,用全局命名空间中的后缀声明一个新的类型。POSIX不是C++,所以一个新的类型不会嵌套。在
std
中编辑,它将是全局的。如果该类型与现有代码库中的类型冲突,则该代码库将被视为(并且一直是)在这种情况下,POSIX与大型库和一些相当有影响力的C++开发人员有很大的出入。我想,如果我们想要超级安全的话,我们可以认为,除了在全局命名空间之外,任何类型的命名空间都允许一个类型的类型,因为这是唯一一个可能轮询的类型。