Using a custom comparator for std::map on IBM i-Series

113 views Asked by At

I'm trying to use a std::map where the keys are c-style strings rather than std::strings but am having problems getting it to compile on an IBM iSeries targetting v7r1m0

I'd like to use c-style strings because using the Performance Explorer (PEX) it appears that the creation of lots of temporary strings for the purpose of map lookups is very expensive.

To do this I have used a custom comparator but when compiling on the iSeries I get an error:

"/QIBM/include/t/xtree.t", line 457.30: CZP0218(30) The call does not
match any parameter list for "const mycompany::myapp::cmp_str::operator()".
"/QIBM/include/t/xtree.t", line 457.21: CZP1289(0) The implicit object
parameter of type "mycompany::myapp::cmp_str &" cannot be initialized with an implied argument of type "const mycompany::myapp::cmp_str".

My comparator is defined as:

struct cmp_str 
{
    bool operator()(char const *a, char const *b)
    {
        return std::strcmp(a, b) < 0;
    }
};

and used in a map :

class LocalSchema : public RecordSchema
{
    public:
        int Operation;
        //map<string, int> FieldLookup;
        map<char *, int, cmp_str> FieldLookup;
};

Am I doing something stupid?

EDIT: changing to

std::map<char const*, int, cmp_str>

gives the same error. Looking in to the job log further I see that this error was produced while processing the following function:

inline int VxSubfile::IndexOfFieldInSchema(char * columnName)
{
    std::map<char const*, int, cmp_str>::iterator iter = _fieldLookup.find(columnName);
    if(iter == _fieldLookup.end())
    {
        return -1;
    }
    else{
        jdebug("Returning index : %d", iter->second);
        return iter->second;
    }
}
1

There are 1 answers

3
Cheers and hth. - Alf On BEST ANSWER

Change

map<char *, int, cmp_str>

to

std::map<char const*, int, cmp_str>

that is, with std::, and with const.

Edit: Also make the comparison member function const, i.e.

struct cmp_str 
{
    bool operator()(char const *a, char const *b) const
    {
        return std::strcmp(a, b) < 0;
    }
};

Note 1: IBM's C++ compilers are infamous for being non-conforming in subtle ways, so you may still run into problems.

Note 2: You need to ensure that the strings outlive the map. E.g. you can use a vector<unique_ptr<char const[]>> as owner for the strings, allowing you to clean up.