2012-04-23 103 views
1

我有這個代碼依賴於SFINAE和默認的模板參數。它的工作原理正如所料,除了最後兩註釋行:函數模板重載的地址

#include <tuple> 
#include <iostream> 
using namespace std; 

template<typename T> void push(T val){ 
    cout<<val<<endl; 
} 

template<typename T> T to(){ 
    T dummy; 
    cin>>dummy; 
    return dummy; 
} 

template<typename T, T> class function_proxy{ 
    static_assert(sizeof(T)!=sizeof(T), "Error: function_proxy works with functions (duh)"); 
}; 

template<typename Return, typename... Args, Return(*func)(Args...)> class function_proxy<Return(*)(Args...), func>{ 
    static Return call(Args... args){ 
     return func(args...); 
    } 
    template<typename... retrieved> static Return call(retrieved... read){ 
     return call(read..., to<typename tuple_element<sizeof...(read), tuple<Args...> >::type >()); 
    } 
public: 
    template<typename Ret=Return, typename enable_if<!is_void<Ret>::value, int>::type=0> 
    static int wrapper(){ 
     push(call()); 
     return 1; 
    } 

    template<typename Ret=Return, typename enable_if<is_void<Ret>::value, int>::type=0> 
    static int wrapper(){ 
     call(); 
     return 0; 
    } 
}; 

int f(int arg){ return arg*3; } 
void g(){ cout<<"g does nothing"<<endl; } 

int main(){ 
    //SFINAE works nicely 
    function_proxy<decltype(&f), &f>::wrapper(); 
    function_proxy<decltype(&g), &g>::wrapper(); 
    //Here it doesn't, even though there should be no ambiguity: 
    //function_proxy<decltype(&f), &f>::wrapper; 
    //function_proxy<decltype(&g), &g>::wrapper; 
} 

你可以看到,當我打電話的模板功能,SFINAE它的工作。但是,當我嘗試使用唯一不合格的函數地址時,g ++會抱怨它無法解析重載函數的地址。

有沒有辦法解決這個問題,而不明確告訴這些重載函數的第一個模板參數?理論上,這是多餘的。另外,我的代碼使用這個輔助類是非常通用的,所以這裏的fg的返回類型可能不是那麼微不足道。

回答

0

SFINAE僅適用於重載解析期間,如果沒有函數調用,則不存在重載解析。

+0

我明白了。關鍵是我認爲這絕對是安全的,當你以這種方式採取地址時,擁有SFINAE是有意義的。有沒有機會在未來的標準中看到這種情況? – 2012-04-24 06:53:48

+0

@LorenzoPistone - 誰知道。 SFINAE的這種內省式使用不是原來建議的重點,它集中在平衡診斷,易用性(模板和函數調用)以及易於編譯器實現(類型推導,重載解析)上。其他一些語言確實具有標準的自省功能,也許C++有一天會跟上訴訟。或者,未來可能會給我們帶來更多的SFINAE。 – 2012-04-24 14:20:25