【问题标题】:C++ template function for method with a parameter of a const type or simply of type带有 const 类型或简单类型参数的方法的 C++ 模板函数
【发布时间】:2016-05-16 00:52:55
【问题描述】:

假设我对调用类方法的两个模板函数有相同的主体,如下所示:

 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)
{
...
}

我尝试写一次body,那么当被调用的方法有参数const并且当它有参数not @987654324时,让编译器使用它的正确方法是什么@?

【问题讨论】:

  • 您可以将函数指针作为模板typename Func。顺便说一句,您的模板看起来都很奇怪。
  • 这只是一个案例,我还有一些其他的函数类型要调用。我绑定了一些我无法触及的第三方 API,因此我需要使用模板进行参数化。
  • 这看起来甚至不会编译给我。非默认模板参数不能跟随默认模板参数。
  • 他们编译。但是拥有两次身体是多余的......
  • @SamVarshavchik 这有点棘手,但他们可以,原因是可能会发生额外的类型推导,其中一些默认参数可能不会输入。示例here.

标签: c++ templates traits template-argument-deduction


【解决方案1】:

您不需要模板化所有这些类型。只有第一个会做。如果您可以使用第一个模板类型推断出其余类型,那么您应该没问题。如果可以从第一个模板类型推导出来,则不需要模板中的私有类型。查看以下代码

#include <iostream>
using std::cout;
using std::endl;
#include <vector>
using std::vector;

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 function(TYPE object, void (TYPE::*member_func_pointer)(int&)) {
    typename TYPE::ClassType a = 1;
    (object.*member_func_pointer)(a);
}

template <typename TYPE>
void function(TYPE object, void (TYPE::*member_func_pointer)(const int&)) {
    typename TYPE::ClassType a = 1;
    (object.*member_func_pointer)(a);
}

int main() {
    A a;
    B b;

    function(a, &A::print_const_integer);
    function(a, &A::print_integer);
    function(b, &B::print_integer);

    return 0;
}

希望有所帮助!

【讨论】:

  • 这是我现在已经拥有的。除了 (object.*member_func_pointer)(a); 之外,我有一个大身体,就像你的例子一样,两次。所以,我希望我可以使用一些std::enable_ifstd::is_same 和相关的东西来将你的示例function 中调用的两个函数减少为一个。
【解决方案2】:

这是一个解决方案,但是,有没有更好的方法?

#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;
}

【讨论】:

    【解决方案3】:

    我这里有另一种方法,它看起来更适合与宏一起使用:

    #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, typename FUNCTYPE>
     struct opt_const_param_function3 : 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_function3<TYPE, FUNCTYPE>::type member_func_pointer> //FUNCTYPE member_func_pointer>
    void function3(TYPE object) {
        typename TYPE::ClassType a = 1;
        (object.*member_func_pointer)(a);
    }
    
    template <typename TYPE, void(TYPE::*member_func_pointer)(int&)>
    void function3(TYPE object) {
        function3<TYPE, decltype(member_func_pointer), member_func_pointer>(object);
    }
    
    template <typename TYPE, void(TYPE::*member_func_pointer)(const int&)>
    void function3(TYPE object) {
        function3<TYPE, decltype(member_func_pointer), member_func_pointer>(object);
    }
    
    int main() {
        A a;
        B b;
    
        function3<A, &A::print_const_integer>(a);
        function3<A, &A::print_integer>(a);
        function3<B, &B::print_integer>(b);
    
        return 0;
    }
    

    有什么想法吗?

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-11-06
      • 1970-01-01
      • 2013-01-22
      • 2015-11-10
      • 2020-04-12
      • 1970-01-01
      • 1970-01-01
      • 2011-08-25
      相关资源
      最近更新 更多