programing

C ++ 11에서 쌍 범위 액세스가 제거 된 이유는 무엇입니까?

sourcetip 2021. 1. 15. 20:24
반응형

C ++ 11에서 쌍 범위 액세스가 제거 된 이유는 무엇입니까?


I는 한 시점에서 C ++ 11 초안 한 것으로 발견 std::begin/ std::end대 과부하 std::pair그 범위를 기반 루프에 사용하기에 적합한 범위 (N3126, 섹션 20.3.5.5)으로 한쌍의 반복자 치료를 허용하지만, 이것은 보유 이후 제거되었습니다.

제거 된 이유를 아는 사람이 있습니까?

한 쌍의 반복자를 범위로 처리하는 다른 방법이 없기 때문에 제거가 매우 불행하다는 것을 알았습니다. 과연:

  • 범위 기반 for 루프에서 시작 / 끝에 대한 조회 규칙은 시작 / 끝이 1) 범위 개체의 멤버 함수로 2) "관련 네임 스페이스"의 자유 함수로 검색된다고 말합니다.
  • std::pair 시작 / 종료 멤버 기능이 없습니다.
  • std::pair<T, U>일반적으로 관련된 유일한 네임 스페이스 는 네임 스페이스 std입니다.
  • 우리는 과부하에 허용되지 않습니다 std::begin/ std::end대한 std::pair자신
  • 우리는 전문 수 std::begin/ std::end위해 std::pair(전문화가 부분적 일해야하고이 기능에 사용할 수 없습니다 있기 때문에)

내가 놓친 다른 방법이 있습니까?


나는 Alisdair Meredith가 쓴 2009 년 논문 "쌍은 좋은 범위를 만들지 못한다" 가 적어도 답의 일부 라고 생각합니다 . 기본적으로 많은 알고리즘은 실제로 유효한 범위가 보장되지 않는 반복기 쌍을 반환합니다. pair<iterator,iterator>이러한 이유로 for-range 루프에서에 대한 지원을 제거한 것으로 보입니다 . 그러나 제안 된 솔루션은 완전히 채택되지 않았습니다.

어떤 이터레이터 쌍이 실제로 유효한 범위나타내는 것을 확실히 알고 있다면 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))) {
       ...
    }
}

(미정)

나는 이것이 약간의 사마귀라는 것에 동의합니다. 유효한 범위 (예 : equal_range)를 반환하는 함수는 적절한 반환 유형을 사용하여 그렇게 말해야합니다. as_range위와 같은 방법으로이를 수동으로 확인해야하는 것은 조금 당황 스럽습니다 .


사용할 수 있습니다 boost::make_iterator_range. begin()end()메서드를 사용 하여 iterator_range를 생성합니다 . 반복자 boost::make_iterator_range를 받아 들일 수 있습니다 std::pair.


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

참조 URL : https://stackoverflow.com/questions/6167598/why-was-pair-range-access-removed-from-c11

반응형