2012-04-23 6 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を使うのが理にかなっています。これが将来の標準で起こるのを見る機会はありますか? –

+0

@LorenzoPistone - 誰が知っていますか? SFINAEのこのようなイントロスペクションのような使用は、診断、使いやすさ(テンプレートと関数呼び出し)、コンパイラの実装の容易性(型減算、過負荷解決)のバランスに焦点を当てた元の提案の一部ではありませんでした。他の言語の中には標準的なイントロスペクション機能があり、C++はいつかその訴訟に従うかもしれません。あるいは、将来はSFINAEをもっともたらすかもしれません。 –

関連する問題