Search code examples
c++functor

Type signature of comparison function object


How can I use a comparison function object type in a method signature? Eg., this is all fine:

struct compInt {
    bool operator() (const int a, const int b) { return a < b; }
};  

set<int,compInt> s1; 

// Actually this is no good, but removing it would obfuscate
// the accepted answer:
set<int> s2(compInt);  

[The last one compiles but it's a function declaration, s2 turns out not to be a container].

But I want to do this:

void func (____ x)
{
    set<int> s(x);
}

I do not want to do this:

template<typename C>
void func (C& c)
{
    set<int> s(c);
}

And function<bool(const int,const int)> does not work. I tried making compInt::operator() virtual so I could do this:

void func (compInt& ci)

And pass in derived objects, but in fact set<int> s(ci) then fails to compile (which I'm almost grateful for, because it is a horrid hack).


Solution

  • set<int> s1(compInt);
    

    This declares a function whose return type is set<int>.

    set<int> s(x);
    

    This declares a local variable of type set<int>. The comparator type is not deduced from the argument, but instead the default template argument is used. As such, compInt is not used as the comparator, so you cannot pass an instance of compInt to the constructor.

    You can use:

    void func (compInt x)
    {
        std::set<int,compInt> s(x);
    

    I tried making compInt::operator() virtual so I could do this:

    void func (compInt& ci)
    

    Polymorphic comparator would be quite problematic. Set stores the object by value, so passing into the function through a reference would not help. You would need to use type erasure: Define a wrapper comparator that takes a polymorphic comparator as constructor argument, stores it in dynamic storage, and delegates the call operator to the stored polymorphic comparator. Then use the wrapper type as the template argument of the set.