c++11templates

How to pass function in class template without use of auto?


I have the following function:

bool comp(Arm l, Arm r) {
    return l.len < r.len;
}

Please, assume Arm is an appropriately declared struct.

I have the following class:

template<typename T, typename F>
class Myclass {
public:
    Arm v[10];
    bool Myfunc(int i) {
        int l = i, r = i + 1;
        return F(v[l], v[s]);
    }
};

When creating the object:

Myclass<Arm, decltype(comp)> obj;

I'm getting the error: expression list treated as compound expression in functional cast [-fpermissive]

I have tried passing the address. I have also tried creating a function pointer and passing that. I wish to get it working for C++ 11. Using C++ 17 I got it working using:

template<typename T, auto F>
class Myclass {
...

And creating the object by:

Myclass<Arm, comp> obj;

And this was working fine.

Example in C++ 11 giving the error:

struct Arm {
    int len;
};

template<typename T, typename F>
class Myclass {
public:
    Arm v[10];
    bool Myfunc(int i) {
        int l = i, r = i + 1;
        return F(v[l], v[r]);
    }
};

bool comp(Arm l, Arm r) {
  return l.len < r.len;
}

int main() {
    Myclass<Arm, decltype(comp)> obj;
    obj.Myfunc(2);
    return 0;
}

Solution

  • Prior to C++17 (which can use auto for the template parameter type), it's usually simplest to create a functor, like a lambda or a struct with an operator() overload:

    struct comp {
        bool operator()(Arm l, Arm r) const { return l.len < r.len; }
    };
    

    With that, you need to instantiate the functor when needing it (or store an instance in your class):

    template<typename T, typename F>
    class Myclass {
    public:
        // ...
        bool Myfunc(int i) {
            int l = i, r = i + 1;
            return F{}(v[l], v[r]);
    //              ^^
    //     instantiate the functor
        }
    };
    

    And since comp is now a type, you can instantiate your Myclass like so:

    Myclass<Arm, comp> obj;
    

    Demo


    Without a functor, you could specify the function signature in the template parameter list to make F a function pointer:

    struct Arm {
        int len;
    };
    
    template <typename T, bool(*F)(T, T)>
    //                    ^^^^^^^^^^^^^^
    //            the function signature it accepts
    class Myclass {
    public:
        Arm v[10];
        bool Myfunc(int i) {
            int l = i, r = i + 1;
            return F(v[l], v[r]); // no instantiation needed
        }
    };
    
    bool comp(Arm l, Arm r) { return l.len < r.len; }
    
    int main() {
        Myclass<Arm, comp> obj;
        obj.Myfunc(2);
    }
    

    Demo