Search code examples
c++templatestraitstemplate-argument-deduction

C++ template function for method with a parameter of a const type or simply of type


Assuming I have the same body for two template functions for calling class methods, like these:

 template <typename jsType, typename jsParamType, typename ParamPrivateType = jsParamType::PrivateType, void(PrivateType::*Method)(const ParamPrivateType&)>
    static bool SetByRefMethod(JSContext *cx, unsigned argc, JS::Value *vp)
{
...
}

 template <typename jsType, typename jsParamType, typename ParamPrivateType = jsParamType::PrivateType, void(PrivateType::*Method)(      ParamPrivateType&)>
    static bool SetByRefMethod(JSContext *cx, unsigned argc, JS::Value *vp)
{
...
}

I try to write once the body, so what is the right way to make the compiler to use it when the called method has a parameter const and when it has a parameter not const?


Solution

  • Here is a solution, but, is there a better way?

    #include <iostream>
    using std::cout;
    using std::endl;
    #include <vector>
    using std::vector;
    #include <type_traits>
    
    class A {
    public:
        using ClassType = int;
    
        void print_const_integer(const int& a) {
            cout << "A's member function accepting a const ref called" << endl;
            cout << a << endl;
        }
    
        void print_integer(int& a) {
            cout << "A's member function accepting a ref called" << endl;
            cout << a << endl;
        }
    
    };
    class B {
    public:
        using ClassType = int;
    
        void print_integer(int& a) {
            cout << "B's member function called" << endl;
            cout << a << endl;
        }
    };
    
    template <typename TYPE, void(TYPE::*member_func_pointer)(int&)>
    void function(TYPE object) {
        typename TYPE::ClassType a = 1;
        (object.*member_func_pointer)(a);
    }
    
    template <typename TYPE, void(TYPE::*member_func_pointer)(const int&)>
    void function(TYPE object) {
        typename TYPE::ClassType a = 1;
        (object.*member_func_pointer)(a);
    }
    
    
    template <typename TYPE, typename FUNCTYPE>
     struct opt_const_param : std::enable_if<std::is_same<FUNCTYPE, void(TYPE::*)(      int&)>::value
                                          || std::is_same<FUNCTYPE, void(TYPE::*)(const int&)>::value, FUNCTYPE>
    {
    };
    
    template <typename TYPE, typename FUNCTYPE, typename opt_const_param<TYPE, FUNCTYPE>::type member_func_pointer>
    void function2(TYPE object) {
        typename TYPE::ClassType a = 1;
        (object.*member_func_pointer)(a);
    }
    
    int main() {
        A a;
        B b;
    
        function2<A, void(A::*)(const int&), &A::print_const_integer>(a);
        function2<A, void(A::*)(int&), &A::print_integer>(a);
        function2<B, void(B::*)(int&), &B::print_integer>(b);
    
        return 0;
    }