2014-07-22 34 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的解決方案,然後查看它是否具有性能成本,因爲代碼非常簡單且易於閱讀。