2014-07-22 33 views
4

我想要一个模板类(包装器),它可以采用所有可能的类(T)并且使用这些类的成员函数(在这里评估)功能)。任意类的const和非const成员函数的模板包装器

我发现了类似的请求,您可以看到herehere,但都不能满足以下两个条件。

条件:

  1. 两个,一个指针到类(T * PTR)的实例和指针成员函数(功能)必须是包装类内访问。

  2. 包装类应与const,non-const成员函数一起使用。

这里说的只对非const工作的代码:

#include <iostream> 
#include <math.h> 

template< class T, double (T::*fck) (double) > 
struct Wrapper 
{ 
    Wrapper(T * ptrT); 

    double evaluate(double); 

protected: 

    T * myPtrT; 
}; 


template< class T, double (T::*fck) (double) > 
Wrapper<T, fck>::Wrapper(T * ptrT) : myPtrT(ptrT) {} 


template< class T, double (T::*fck) (double) > 
double Wrapper<T, fck>::evaluate(double s) 
{ return (myPtrT->*fck)(s); } 


struct kernel 
{ 
    double gauss(double s) 
    { 
    return exp(-0.5*s*s); 
    } 
}; 

int main() 
{ 
    kernel G; 

    Wrapper<kernel, &kernel::gauss> myKernel (&G); 

    std::cout<< myKernel.evaluate(0.0) <<std::endl; 
    std::cout<< myKernel.evaluate(0.3) <<std::endl; 

    return 0; 
} 

回答

3

是在Wrapper类严格必要吗?看起来您正在尝试为提供标准签名的函数的类创建通用评估机制:double f(double)。这很容易使用std::function(C++ 11)或boost::function(C++ 03)来解决。

在C++ 03使用boost::functionboost::bind

#include <boost/function.hpp> 
#include <boost/bind.hpp> 
#include <iostream> 
#include <math.h> 

struct kernel 
{ 
    double gauss(double s) 
    { 
    return exp(-0.5*s*s); 
    } 
}; 

int main() 
{ 
    kernel G; 

    typedef boost::function<double (double)> MyWrapper; 

    MyWrapper w(boost::bind(&kernel::gauss, G, _1)); 
    std::cout << w(0.0) << std::endl; 
    std::cout << w(0.3) << std::endl; 

    return 0; 
} 
2

所有的编程问题都可以通过抽象的另一个层面来解决,除了抽象的层次太多。

template< class T, class Op > 
struct Wrapper 
{ 
    Wrapper():t(nullptr){} 
    Wrapper(T* ptrT):t(ptrT){} 
    Wrapper(Wrapper const&) = default; 
    Wrapper& operator=(Wrapper const&) = default; 

    template<class...Args> 
    auto operator()(Args&&...args) const->decltype(Op{}(std::declval<T*>(),std::declval<Args>()...)) { 
    return Op{}(t, std::forward<Args>(args)...); 
    } 
    T* t; 
}; 

template< class T, bool isConst, class Sig > 
struct MemberFunc; 
template< class T, class R, class... Args > 
struct MemberFunc<T, false, R(Args...) > { 
    template< R(T::*func)(Args...) > 
    struct type { 
    template<class... Ts> 
    R operator()(T* t, Ts&&...ts) const { 
     return (t->*func)(std::forward<Ts>(ts)...); 
    } 
    }; 
}; 
template< class T, class R, class... Args > 
struct MemberFunc<T, true, R(Args...) > { 
    template< R(T::*func)(Args...) const > 
    struct type { 
    template<class... Ts> 
    R operator()(T const* t, Ts&&...ts) const { 
     return (t->*func)(std::forward<Ts>(ts)...); 
    } 
    }; 
}; 

struct kernel 
{ 
    double gauss(double s) 
    { 
    return exp(-0.5*s*s); 
    } 
}; 

int main() 
{ 
    kernel G; 

    Wrapper<kernel, MemberFunc<kernel, false, double(double)>::type<&kernel::gauss>> myKernel(&G); 

    std::cout<< myKernel(0.0) <<std::endl; 
    std::cout<< myKernel(0.3) <<std::endl; 

    return 0; 
} 

live example

MemberFunc::type基本上是一个编译时评价std::mem_fun

Wrapper现在需要一个无状态仿函数作为它的第二个参数,它完美地转向了。 MemberFunc<...>::type<...>构建这样一个包装成员函数的无状态仿函数。

我冒昧地使它与任意函数签名一起工作,并且摆脱了.evaluate - 我们有一个invokation操作符,如果我们有一个要调用它的工作的实例,就调用它。

当然,这也可以用做拉姆达:

auto myKernel = [G](double s)->double { return G->gauss(s); }; 

myKernel类型不允许将其轻松地存储并没有在某些情况下,返回的类型擦除它。删除类型会增加运行时间间隔,这会产生运行时间成本。

您应该先尝试先删除型号std::function的解决方案,然后查看它是否具有性能成本,因为代码非常简单且易于阅读。