2010-02-03 2 views
2
중간 결과의 유형이 대상 유형에 의존하지 않기 때문에이 코드는 오버 플로우 앓고

그러나암시 홍보 :: partial_sum

vector<uint8_t> increments; 
… 
vector<uint32_t> increasing(increments.size()); 
partial_sum(increments.begin(), increments.end(), increasing.begin()); 

, 그래서이 (GCC 4.2)를 수행합니다

partial_sum(increments.begin(), increments.end(), increasing.begin(), 
      plus<uint32_t>()); 

plus<uint32_t> 피연산자를 홍보하고 오버플로를 방지해야합니까?

편집 : 저는 너무 중독되었습니다. 짧은 휴식 후에, 나는 다시 앉아서 구현을 점검했다. ...

/* input_iterator::value_type */ __value = __binary_op(__value, *__first); 
    *++__result = __value; 

내가 그 준수 생각하지 않는다, 그래서 최신 버전을 확인하고 어쩌면 버그를 제출할 수 있습니다 여기에 우리가 간다 : 이것이 수행 http://gcc.gnu.org/bugzilla/show_bug.cgi?id=42943

+0

나는 당신이 옳다고 생각한다. 문제는 '더하기'가 매개 변수를 변환하는지 여부이다. 물론 문제는 26.4.3/1에서 두 번째 출력에 할당 된 값이' 하지만 InputInterator :: value_type (binary_op (* first, * (first + 1)))이 아닌 binary_op (* first, * (first + 1) 그것은 그것을 사용하고있을 수 있지만, 함수는 result_type을 가지고 있지 않으며, 확실히 partial_sum에 함수 포인터를 전달할 수 있습니까? 아마도 나에게 너무 늦었을 것입니다 ... –

+0

아, 함수 포인터. §25/8 (sorta)을 제외하고는 연산 객체에 대한 특정 요구 사항을 찾을 수 없으며 두 개의 인수로 호출 할 수 있습니다. 템플릿은 함수에서 반환 유형을 추출 할 수 있지만 변경 사항이 더 큰 영향을줍니다. – Potatoswatter

+0

BinaryFunction에서 유형을 추론하는 대신 InputIterator 유형 대신 OutputIterator의 value_type을 사용하지 않는 이유는 무엇입니까? – visitor

답변

1

따르면 http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#539에, partial_sum가있다 n3000 (최신 릴리스) 이후 완전히 재정의 됨 :

효과 : VT를 InputIterator의 값 유형으로합시다. 비어 있지 않은 범위의 경우 은 * first를 사용하여 VT의 누적 기 acc을 초기화하고 * result = acc를 수행합니다. 첫 번째 1에있는 모든 반복자에 대해 acc는 이 acc = acc + * i 또는 acc = binary_op (acc, * i)로 수정되고 * (결과 + (i) - 처음)).

'확대'동작은 다음 다소 관여 맞춤 프록시 반복기를 작성함으로써 얻어진다.

정말 이런 식으로 일하는 장점을 볼 수 없습니다. 결함 보고서를 읽고, 나는 알고리즘의 목적은 입력 반복자의 유형을 사용하여 계산을 수행하는 것입니다

외에 어떤 정당성을 볼 수 없습니다.

아라비아

편집 : 확장 입력 반복기를 구현했습니다. 광고 된대로 작동합니다.

template< class Base, class Wider > 
struct widen_iter : iterator< input_iterator_tag, Wider > { 
    Base b; 
    widen_iter(Base const &inb = Base()) : b(inb) {} 
    Wider operator*() const { return Wider(*b); } 
    Wider const *operator->() const { Wider t(*b), *ta = &t; return ta; } 
    widen_iter &operator++() { ++ b; return *this; } 
    widen_iter operator++(int) { widen_iter t = *this; ++ b; return t; } 
    bool operator==(widen_iter const &r) const { return b == r.b; } 
    bool operator!=(widen_iter const &r) const { return b != r.b; } 
}; 
template< class Wider, class Base > 
widen_iter< Base, Wider > 
widener(Base b) { return widen_iter< Base, Wider >(b); } 

일반 필 터별 입력기 반복기가있는 경우 훨씬 짧아집니다.

+0

대신에 std :: accumulate를 사용하고, 'init' 값은 출력 반복자를 저장하고 증분하며 더 넓은 유형을 사용하여 누적 합계를 저장합니다. 누적은 추가가 순서대로 수행됨을 보장합니다. –

+0

+1 오버플로를 피하는 것이 오버플로를 달성하는 것보다 어렵게해야하는 이유를 알 수 없습니다. 해결책 : 자신 만의 partial_sum을 작성 하시겠습니까? – UncleBens

+0

@ 스티브 : 그것은 더 짧은 해결책 일 수 있습니다. 'init'은'operator +'와'operator ='만 구현하면됩니다. 매우 구체적입니다. @Uncle : 그래, 그게 더 현실적인 해결책이 될 것 같은데, 제대로 (fn ptrs를 받아들이면) 템플리트 인트로 스펙 션이 필요할 것이다. – Potatoswatter