2012-09-30 2 views
5

나는 현재 배열이나 원시 데이터의 벡터를 (_readStreamstd::ifstream입니다) 읽을 수있는 다음과 같은 기능을 가지고 :반복자가 연속 메모리 영역을 형성하는지 여부를 확인하는 방법은 무엇입니까?

template<typename IteratorType> 
inline bool MyClass::readRawData(
    const IteratorType& first, 
    const IteratorType& last, 
    typename std::iterator_traits<IteratorType>::iterator_category* = nullptr 
    ) 
{ 
    _readStream.read(reinterpret_cast<char*>(&*first), (last-first)*sizeof(*first)); 
    return _readStream.good(); 
} 

첫 번째 질문 :이 기능을 사용하면 괜찮을 것입니까?

우리는 직접 메모리 블록을 읽었으므로 first에서 last까지의 메모리 블록이 메모리에서 인접 해있는 경우에만 작동합니다. 그것을 확인하는 방법? std::iterator_traits가 unconditonally 정의 부재 형 iterator_category와 기본 템플릿을 갖기 때문에

+0

함수는 함수 사용 방법에 대해 많은 가정을합니다. 그들이 명백하거나 적어도 문서화되어 있다면 더 좋을 것입니다. 이러한 가정들 중에서 : 1) 그 요소들은 메모리에서 이진 표현에 의해 직렬화 될 수 있습니다. 2) 런타임의 endianess는 데이터를 작성한 endianess와 동일합니다. – Cameron

+3

사실, 함수가 완전히 비 제너릭 일 때 반복자를 사용하는 이유는 무엇입니까? 그 유일한 목적은 원소들을 비트 단위로 메모리에 복사하는 것입니다. 이것을 반영하기 위해 함수의 이름을 변경하고 iterators 대신 포인터와 카운트를 가져 오십시오 ... 제목에있는 질문은 여전히 ​​흥미 롭습니다 :-) – Cameron

+0

엔디안이 다른 경우 데이터를 바꿀 수있는 또 다른 함수가 있습니다. 두 번째 문제는 문제가되지 않습니다. – Vincent

답변

4

샘플 함수를 제외하고 이터레이터가 둘 사이의 모든 요소의 주소를 확인하지 않고 연속 메모리를 형성한다는 것을 완전히 확신 할 수는 없습니다.

assert(&*last - &*first == last - first && 
    "Iterators must represent a contiguous memory region"); 
+1

'* * last - & * first'는'* first'와'* first'가 정의되지 않은 동작이 아니라면, 마지막 '같은 배열의 일부이며, 우리가 결정하려고하는 바로 그 것입니다. –

+0

@BenjaminLindley 나는 그것이 정의되지 않을 것이라고 생각하지 않는다. 그것은 단순한 포인터 뺄셈이다. 컨테이너가 인접하지 않은 경우 음수 값과 같은 이상한 결과가 표시 될 수 있지만 두 반복자 사이의 거리에 대해 확인됩니다. 적어도 포스터는 컨테이너가 연속적이든 아니든 동일한 컨테이너의 임의 액세스 반복자를 요구하는 알고리즘을 요구할 것이라고 생각하는 것이 상당히 안전하다고 생각합니다. 그럼에도 포스터가하려는 이상한 일입니다. – stinky472

+7

@ stinky472 : 예, 포인터 뺄셈이라고 알고 있습니다. 제가 말하고자하는 것은 포인터가 동일한 배열의 객체를 가리 키지 않는 한 빼기 연산은 표준에 따라 정의되지 않습니다. 5.7.6 –

2
typename std::iterator_traits<IteratorType>::iterator_category* = nullptr 

이 쓸모 없다. 템플리트 매개 변수는 반복자이고, 그렇지 않은 경우 전제 조건 위반이라고 가정합니다. SFINAE를 얻지는 못하지만 유효하지 않은 인스턴스화로 위의 시도를 시도하면 하드 오류가 발생합니다.

처음으로 메모리 블록을 읽었을 때 메모리 블록이 처음부터 마지막까지 연속적으로 메모리에있는 경우에만 작동합니다. 그것을 확인하는 방법?

정확한 '메모리 부족'개념을 정확히 알지 못합니다. 그러나 다음 사항을 고려 했습니까? 배열로 유효한 포인터로서의 반복기 범위 일 [ first, last) 전제로

template<typename T> 
bool readRawData(T* first, T* last); 

.

T에 대한 추가 요구 사항 (예 : read을 사용 했으므로 사소한 복사 가능성)을 추가로 표현하려면 해당 내용도 표현/문서화 할 수 있습니다.

3

n4183가의 아이디어를 넘어 종이입니다 : 둘 사이의 메모리 영역은 둘 사이의 수가 같은 경우

합리적인 정신 테스트,하지만 단지 확인하는 것입니다 인접 반복자 특성을 추가합니다. 그것은 현재 C++ 1z (잘하면 C++ 17)에 대한 고려 중입니다.

아래에서 std::is_contiguous_iterator<It>::value을 수행하고 It이 연속 반복자인지 여부를 확인할 수 있습니다. (반복기 디자이너의 지원이 필요합니다.)

+0

이게 받아 들여 졌습니까? – einpoklum

관련 문제