0

I'm migrating code from a server with Red Hat Enterprise Linux ES release 3 to a server with Red Hat Enterprise Linux release 7.5. The code compiles successfully on the RH 3 box (with gcc 3.2.3), but not on the RH 7.5 box (with gcc 4.8.5). Here's the header file code in question:

#ifndef FSM_H
#define FSM_H

#include <assert.h>
#include <string>
#include <map>

namespace fsm {

template<class A>
class Event {
    bool (A::*Action)(void);    // Action to peform.  False means it failed.
    std::string gotoState;      // State to transition on success

public:
    Event();
    Event( const Event &rhs );
    Event( bool (A::*Action)(void), const std::string &newState );
    const std::string HandleEvent(A *parent) const;
};


template<class A>
class State : protected std::multimap<const std::string,Event<A> > {
public:
    void addEvent(  const std::string &event,
                bool (A::*Action)(void),
                const std::string &newState);
    const std::string HandleEvent( A *parent, const std::string &event ) const;
};

template<class A>
void State<A>::addEvent(const std::string &event,
                    bool (A::*Action)(void),
                    const std::string &newState )
{
    insert(State<A>::value_type(event,Event<A>( Action, newState )));
}

template<class A>
const std::string State<A>::HandleEvent( A *parent, const std::string &event ) const
{
    typename State<A>::const_iterator i;
    std::string newState;

    for( i=lower_bound(event); i!=upper_bound(event); i++ ) {
        newState = i->second.HandleEvent(parent);
        if ( newState.size() ) return newState;
    }
    return std::string(); 
}

} // namespace fsm
#endif

The compiler complains about the insert, lower_bound, and upper_bound functions; it can't find a matching function for each of these functions. These should be interpreted as functions belonging to std::map, but the compiler appears to be trying to use std::upper_bound and std::lower_bound instead (I'm not sure what insert function the compiler is trying to use).

In order to make it crystal-clear to the compiler, I modified the code so there was no ambiguity that lower_bound, upper_bound, and insert are std::map functions. For example, in this part of the code:

template<class A>
const std::string State<A>::HandleEvent( A *parent, const std::string &event ) const
{
    typename State<A>::const_iterator i;
    std::string newState;

    for( i=lower_bound(event); i!=upper_bound(event); i++ ) {
        newState = i->second.HandleEvent(parent);
        if ( newState.size() ) return newState;
    }
    return std::string(); 
}

I modified the code as follows:

template<class A>
const std::string State<A>::HandleEvent( A *parent, const std::string &event ) const
{
    typename State<A>::const_iterator i;
    typename State<A>::const_iterator lowerBound;
    typename State<A>::const_iterator upperBound;
    std::string newState;

    lowerBound = std::multimap<const std::string, fsm::Event<A>, std::less<const std::string>,
             std::allocator<std::pair<const std::string, fsm::Event<A> > > >::lower_bound(event);
    upperBound = std::multimap<const std::string, fsm::Event<A>, std::less<const std::string>,
             std::allocator<std::pair<const std::string, fsm::Event<A> > > >::upper_bound(event);

    for( i=lowerBound; i!=upperBound; i++ ) {
        newState = i->second.HandleEvent(parent);
        if ( newState.size() ) return newState;
    }
    return std::string();
}

That works, but it's hokey, verbose and ugly. Is there a better way to help the compiler know that it should use the functions from std::map without having to spell it out in such a tedious manner?

Michael Horii
  • 55
  • 1
  • 5

0 Answers0