2

SFINAE とデフォルトのテンプレート引数に依存するこのコードがあります。最後の 2 行のコメント行を除いて、期待どおりに動作します。

#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++ は、オーバーロードされた関数のアドレスを解決できないと不平を言います。

これらのオーバーロードされた関数の最初のテンプレート パラメーターを明示的に伝えずに、この問題を解決する方法はありますか? 理論的には、冗長です。また、このヘルパー クラスを使用する私のコードは非常に汎用的であるため、ここにあるものの戻り値の型は取得するのがそれほど簡単ではfありgません。

4

1 に答える 1

1

SFINAE は、オーバーロードの解決中にのみ適用され、関数呼び出しがない場合、オーバーロードの解決はありません。

于 2012-04-23T22:03:58.137 に答える