loop - list iterator c++




How to adjust vector iterator to return struct? (3)

My 50 cents:

Iterators are generic ways to access any STL container. What I feel you're saying is: Since pointers are OK as a replacement of iterators for vectors, why are there iterators for vectors?

Well, who said you can't have duplicates in C++? Actually it's a good thing to have different interfaces to the same functionality. That should not be a problem.

On the other hand, think about libraries that have algorithms that use iterators. If vectors don't have iterators, it's just an invitation to exceptions (exceptions in the linguistic since, not programming sense). Every time one has to write an algorithm, he must do something different for vectors with pointers. But why? No reason for this hassle. Just interface everything the same way.

As a part of my ongoing task of converting a C++ project from Unix to Linux, I now have the following error:

jh205.C: In member function ‘FVSearchLogical_t* FVLogical::getFirst(long int)’: jh205.C:9615: error: invalid cast from type ‘__gnu_cxx::__normal_iterator > >’ to type ‘FVSearchLogical_t*’ jh205.C: In member function ‘FVSearchLogical_t* FVLogical::getNext(long int)’: jh205.C:9630: error: cannot convert ‘__gnu_cxx::__normal_iterator > >’ to ‘FVSearchLogical_t*’ in return jh205.C: In member function ‘void FVLogical::updateTable()’: jh205.C:9656: error: invalid cast from type ‘__gnu_cxx::__normal_iterator > >’ to type ‘void*’

It comes from this code:

FVSearchLogical_t * FVLogical::getFirst(long sensorId) {

  // loop through the Search vector to find the first one for the sensor
  m_searchLogical_it =  m_FVSearchVector.begin();
  for(int i=0; i < m_FVSearchVector.size(); i++){

    // as soon as we find the first one return it
    if(m_searchLogical_it->ml_sensorId == sensorId) {
      return m_searchLogical_it;
    }
    m_searchLogical_it++;
  }

  return NULL;
}

The struct it is about:

typedef struct {
    long ml_sensorId;
    char mc_startDate[10];
    char mc_startTime[10];
    char mc_endDate[10];
    char mc_endTime[10];
    long ml_startBlk;
    long ml_endBlk;
    long ml_sendUnit;
} FVSearchLogical_t;

Any suggestions on how to do this with the least amount of code changes in the project?

Added information:

FVLogical::~FVLogical(){
  m_FVSearchVector.clear();
  m_FVInsertVector.clear();
  m_rptDataVector.clear();
  m_rptHeaderVector.clear();
  m_rptFooterVector.clear();
}

What those comments are saying is that

template <typename T, ...>
class vector
{
public:
    typedef T* iterator;
    typedef const T* const_iterator;
    ...
private:
    T* elems; // pointer to dynamic array
    size_t count;
    ...
}

is valid. Similarly a user defined container intended for use with std:: algorithms can do that. Then when a template asks for Container::iterator the type it gets back in that instantiation is T*, and that behaves properly.

So the standard requires that vector has a definition for vector::iterator, and you use that in your code. On one platform it is implemented as a pointer into an array, but on a different platform it is something else. Importantly these things behave the same way in all the aspects that the standard specifies.


Does Using a Pointer as a Container Iterator Violate the Standard

§ 24.2.1

Since iterators are an abstraction of pointers, their semantics is a generalization of most of the semantics of pointers in C++. This ensures that every function template that takes iterators works as well with regular pointers.

So yes, using a pointer satisfies all of the requirements for a Random Access Iterator.

std::vector likely provides iterators for a few reasons

  1. The standard says it should.

  2. It would be odd if containers such as std::map or std::set provided iterators while std::vector provided only a value_type* pointer. Iterators provide consistency across the containers library.

  3. It allows for specializations of the vector type eg, std::vector<bool> where a value_type* pointer would not be a valid iterator.