tags:

views:

283

answers:

2

I am trying to change the default order of the items in a set of integers to be lexicographic instead of numeric, and I can't get the following to compile with g++:

file.cpp:

bool lex_compare(const int64_t &a, const int64_t &b) 
{
    stringstream s1,s2;
    s1 << a;
    s2 << b;
    return s1.str() < s2.str();
}

void foo()
{
    set<int64_t, lex_compare> s;
    s.insert(1);
    ...
}

I get the following error:

error: type/value mismatch at argument 2 in template parameter list for ‘template<class _Key, class _Compare, class _Alloc> class std::set’
error:   expected a type, got ‘lex_compare’

what am I doing wrong?

+11  A: 

You are using a function where as you should be using a functor (a class that overloads the () operator so it can be called like a function).

struct lex_compare {
    bool operator() (const int64_t& lhs, const int64_t& rhs) const{
        stringstream s1,s2;
        s1 << a;
        s2 << b;
        return s1.str() < s2.str();
    }
};

You then use the class name as the type parameter

set<int64_t, lex_compare> s;

If you want to avoid the functor boilerplate code you can also use a function pointer (assiming lex_compare is a function)

set<int64_t, bool(*)(const int64_t& lhs, const int64_t& rhs)> s(&lex_compare);
Yacoby
actually my problem appeared to be an extra closing > in the declaration of the set. I am closing the question as bogus.(using a straight function instead of a functor is perfectly okay for STL)
Omry
the code in the question is simpler than what you proposed (for a simple function comparator) and works just fine.
Omry
@Omry: I'd be interested in knowing what compiler you're using: http://codepad.org/IprafuVf
Beh Tou Cheh
@Omry Which compiler are you using?
anon
correction, it's not working fine. my bad.
Omry
@Omry The C++ standard says that the second template parameter must be the name of a type - a function name is not the name of a type.
anon
A: 

Yacoby's answer inspires me to write an adaptor for encapsulating the functor boilerplate.

template< class T, bool (*comp)( T const &, T const & ) >
class set_funcomp {
    struct ftor {
        bool operator()( T const &l, T const &r )
            { return comp( l, r ); }
    };
public:
    typedef std::set< T, ftor > t;
};

// usage

bool my_comparison( foo const &l, foo const &r );
set_funcomp< foo, my_comparison >::t boo; // just the way you want it!

Wow, I think that was worth the trouble!

Potatoswatter
A matter of opinion, I guess.
anon