2012-01-20 29 views
3

受另一個問題的啓發,我試圖找到一種方法來推導出一個重載成員函數的類型 ,給出用於調用 函數的實際參數。以下是我迄今爲止:使用模板元編程執行重載解析

#include <type_traits> 

template<typename F, typename Arg> 
struct mem_fun_type { 
    // perform overload resolution here 
    typedef decltype(std::declval<F>()(std::declval<Arg>())) result_type; 
    typedef decltype(static_cast<result_type (F::*)(Arg)>(&F::operator())) type; 
}; 

struct foo {}; 

struct takes_two 
{ 
    void operator()(int); 
    void operator()(foo); 
}; 

struct take_one { 
    void operator()(float); 
}; 

int main() 
{ 
    static_assert(std::is_same<mem_fun_type<take_one, float>::type, 
          void (take_one::*)(float)>::value, "Zonk"); 
    static_assert(std::is_same<mem_fun_type<takes_two, double>::type, 
          void (takes_two::*)(float)>::value, "Zonk"); 
    return 0; 
} 

只要模板參數精氨酸的實際類型相匹配的 的static_cast會成功,但是這僅僅是 重載解析(精確匹配)的最簡單的情況。是否有可能在模板元編程中執行完整的重載解析過程 ?

這是純粹的假設,不適合現實世界的使用。

+0

這是一個純粹的現實生活中的例子,昨天我用'boost :: bind-vs-std :: bind'發佈了這個問題! – vines

+2

我回答了你提到的[這裏]的問題(http://stackoverflow.com/a/8938409/147192)。沒有客戶的幫助,我只是看不出有關重載解決方案的理由。 –

+0

你是一個貪婪的懲罰者。 –

回答

1

這是最接近我到目前爲止:定義函數返回不同大小的表,並且您的結果是sizeof(select(...))接收指針要匹配的函數。爲確保即使功能在給定的類中不存在,代碼也會被編譯,您可以使用單獨的檢查has_function

重載分辨率的結果在select<has_function<T>::value, T>::value

使用此代碼,您甚至可以「解析」數據成員,而不僅僅是函數,它只是爲選擇函數創建正確參數的問題。

但是這裏有一個缺陷 - 重載分辨率不是函數參數,而是函數類型。意義沒有通常的參數類型轉換髮生。

// Verify the name is valid 
    template <typename T> 
    struct has_function 
    { 
    struct F {int function;}; 
    struct D : T, F {}; 
    template <typename U, U> struct same_; 
    template <typename C> static char(&select_(same_<int F::*, &C::function>*))[1]; 
    template <typename> static char(&select_(...))[2]; 
    enum {value = sizeof(select_<D>(0)) == 2}; 
    }; 

    // Values to report overload results 
    enum type { none=1 , function_sz_size_t , function_sz , function_string }; 

    template <bool, typename R> struct select; 

    template <typename R> struct select<false, R> 
    { 
    enum {value = none}; 
    }; 

    template <typename R> struct select<true, R> 
    { 
    // Define your overloads here, they don't have to be templates. 
    template <typename Ret, typename Arg> static char(&select_(Ret (R::*)(const char*, Arg)))[function_sz_size_t]; 
    template <typename Ret, typename Arg> static char(&select_(Ret (R::*)(Arg)))[function_sz]; 
    template <typename Ret> static char(&select_(Ret (R::*)(std::string)))[function_string]; 
    template <typename Ret> static char(&select_(Ret (R::*)(std::string&&)))[function_string]; 
    template <typename Ret> static char(&select_(Ret (R::*)(const std::string&)))[function_string]; 
    static char(&select_(...))[none]; 
    enum {value = sizeof(select_(&R::function))}; 
    };