1

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();
}
Melebius
  • 6,183
  • 4
  • 39
  • 52
Carmageddon
  • 2,627
  • 4
  • 36
  • 56
  • I'm only guessing, but you have `std::vector`, correct? To get a `FVSearchLogical_t` out of an iterator of that vector you just have to dereference it. Standard iterator behavior. – DeiDei Jan 25 '17 at 12:26
  • 1
    This is highly unidiomatic code. Use a pair of iterators to designate a **range**: an iterator that points at the beginning of the data and an iterator that points past the end of the data. If the desired result is not found, return the end iterator. Once you've adapted the code to that idiomatic use, replace it all with `std::find_if`. – Pete Becker Jan 25 '17 at 13:59

1 Answers1

3

You are trying to return an iterator exactly as the warning says you are in the line:

return m_searchLogical_it;

To get a raw pointer to the element, which is the return type of getFirst, you'll need to get a pointer to the object m_searchLogical_it points to. To do that you'll need to dereference the iterator to get the object, then take the address of the object:

return &*m_serchLogical_it;

If I may additionally suggest; you're using an iterator (m_searchLogical_it) and a loop counter (i), when all you need to use is the iterator:

for(m_searchLogical_it = begin(m_FVSearchVector); m_searchLogical_it != end(m_FVSearchVector); ++m_searchLogical_it) {
    if(m_searchLogical_it->ml_sensorId == sensorId) {
        return &*m_searchLogical_it;
    }
}
Jonathan Mee
  • 37,899
  • 23
  • 129
  • 288
  • Thank you! that works beautifully! I'd love an explanation why, I am not well versed in C++, and the differences between why things work in Unix but not Linux baffle me... – Carmageddon Jan 25 '17 at 12:37
  • 2
    @Carmageddon This has nothing to do with Unix and Linux per se. It's that the "working" code was relying on an implementation detail of the C++ standard library implementation with which it was built (namely that its vector iterators are raw pointers). This implementation detail obviously no longer holds on your new platform & toolchain, hence the error. – Angew is no longer proud of SO Jan 25 '17 at 12:42
  • @Carmageddon I'm not going to be able to give you a good explanation of why this worked previously, unless you were using a non-standard container, which had it's own iterator type defined, which had an cast conversion to pointer defined... So, ahem, yeah, if you were just using `vector` then the fact it compiled at all previously was non-compliant. – Jonathan Mee Jan 25 '17 at 12:44
  • @Angew I wanted to find a definition of the `vector::iterator` class on http://en.cppreference.com to demonstrate that a casting operator had never been defined and thus the previously used compiler was non-compliant, but I couldn't find such a definition. Is the interface of `vector::iterator` is not called out in the standard? I can't seem to find anything on it. – Jonathan Mee Jan 25 '17 at 12:49
  • 2
    @JonathanMee Using a pointer as `vector::iterator` is perfectly legal. All the standard requires from the type `vector::iterator` is to model the `RandomAccessIterator` concept, which a raw pointer certainly does. – Angew is no longer proud of SO Jan 25 '17 at 12:58
  • @Angew Well color me surprised. I've asked a follow up here: http://stackoverflow.com/q/41853089/2642059 but even after I wrote it I think the answer is pretty straightforward. – Jonathan Mee Jan 25 '17 at 13:39