Search code examples
c++inheritancepolymorphismstd-function

Why does using a std::function declared with the parent show me an error when used with a child?


This is the declaration of the virtual Sort-function located in an interface, using a std::function.

using Comparefunction = std::function<bool(const DataHandling::GridDataStruct &d1, const 
DataHandling::GridDataStruct  &d2)>;

virtual bool Sort(const Comparefunction& fct);

This is the function adressed by the std::function:

bool operator() (const Types::Order &d1, const Types::Order &d2)const;

where Types::Order is a child of GridDataStruct.

The std::function is used while the class containing the operator above is instantiated:

 Sort(Tools::OrderComparer(grid, false));

->OrderComparer contains operator showed above

-> Sort also has been mentioned at the top.

If there are any questions respectively a lack of clarity, feel free to ask!

Simplified error message:

No suitable user-defined conversion from (Class containing the operator) to (std::function adressing operator)


Solution

  • This boils down to

    struct Base { virtual ~Base(); };
    
    struct Derived : Base {};
    
    struct Comparer
    {
        bool operator()(const Derived&, const Derived&)
        {
            return true;
        }
    };
    
    std::function<bool(const Base&, const Base&)> comp(Comparer{});
    

    https://godbolt.org/z/_7Xtfn

    comp is supposedly able to compare two Base instances. But Comparer can only compare Derived instances, so it cannot be used to initialize comp.

    Or, to repeat the above comment: The code says "Sort wants a CarComparer" but you only give it a PorscheComparer. The compiler is completely right to be unsatisfied with that - what if somebody uses the CarComparer to compare two Mercedes instances?

    Maybe a PorscheComparer will only ever be used to compare Porsche instances. The clean way to express this would be to template Sort (or the entire interface) on the concrete car type - possibly eliminating the inheritance hierarchy entirely (replacing it with compile-time polymorphism).