2

我有这个依赖于 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++ 抱怨它无法解析重载函数的地址。

有没有办法在不明确告诉这些重载函数的第一个模板参数的情况下解决这个问题?理论上,这是多余的。此外,我使用这个帮助类的代码是非常通用的,所以这里的返回类型是f并且g可能不是那么容易获取。

4

1 回答 1

1

SFINAE 仅在重载决议期间适用,如果没有函数调用,则没有重载决议。

于 2012-04-23T22:03:58.137 回答