template<typename Signature>
class myfunction //basic class template
{
};
template<typename R, typename... Args>
class myfunction<R (Args...)> //normal function specialized edition
{
typedef R (*Ptr)(Args...);
Ptr m_p;
public:
myfunction(Ptr p) : m_p(p)
{
}
R operator()(Args... args)
{
return m_p(args...);
}
};
template<typename R, typename T, typename ... Args>
class myfunction<R (T*, Args...)> //member function specialized edition one
{
typedef R (T::* mPtr)(Args...);
mPtr m_p;
public:
myfunction(mPtr p): m_p(p)
{
}
R operator()(T* likeThis, Args...args)
{
return (likeThis->*m_p)(args...);
}
};
template<typename R, typename T, typename ... Args>
class myfunction<R (T, Args...)> //member function specialized edition two
{
typedef R (T::* mPtr)(Args...);
mPtr m_p;
public:
myfunction(mPtr p): m_p(p)
{
}
R operator()(T likeThis, Args...args)
{
return (likeThis.*m_p)(args...);
}
};
template<typename R, typename T, typename ... Args>
class myfunction<R(T&, Args...)> //member function specialized edition three
{
typedef R (T::* mPtr)(Args...);
mPtr m_p;
public:
myfunction(mPtr p): m_p(p)
{
}
R operator()(T& likeThis, Args...args)
{
return (likeThis.*m_p)(args...);
}
};
int func1()
{
cout << "func1";
return 0;
}
void func2(int x)
{
cout << "func2";
cout << x ;
}
int main()
{
myfunction<int(void)> f1(func1);
f1();
myfunction<void(int)> f2(func2);//this will fail, why?
f2(1);
return 0;
}
我想在标准库中修改函数包装器。 测试代码如上所述。 但是,f1可以算一个合适的,这是正常的功能专用版。虽然f2首先匹配成员函数专用版本两个,但是匹配失败后,应该去匹配正常功能专用版然后成功吗?这就是SFINAE的意思,对不对? 在我评论出会员功能专业版二之后,它会匹配一个,那为什么? 请帮帮我。
答案 0 :(得分:0)
正如评论中指出的那样 - 这个专业化正在接管你的一个arg自由函数:
template<typename R, typename T, typename ... Args>
class myfunction<R (T, Args...)> //member function specialized edition two
{
typedef R (T::* mPtr)(Args...);
mPtr m_p;
public:
myfunction(mPtr p): m_p(p)
{
}
R operator()(T likeThis, Args...args)
{
return (likeThis.*m_p)(args...);
}
};
简单回答就是删除此专业化,您的程序开始编译。
但是 - std::function
实现并不像你想象的那么容易。您需要使用type erasure技术来模仿其行为 - 我的意思是myFunction<R(Arg...>
级myFunction
应该为所有 - 免费函数和成员函数服务 - 仅在构造特定对象实例时 - 您应该选择&#34;实施&#34;通过参数类型 - 如果它是成员函数或自由函数。
首先,您必须定义任何函数调用抽象:
template<typename R, typename T, typename ... Args>
class AnyFunctionCall
{
public:
virtual ~AnyFunctionCall() {}
virtual R call(T arg, Arg&&... args) const = 0;
};
我看到你已经知道如何为自由函数和成员函数实现这个接口。
template<typename R, typename T, typename ... Args>
class myfunction<R (T, Args...)>
{
std::unique_ptr<AnyFunctionCall> implementation;
public:
template <typename Functor>
myfunction(Functor p): m_p(makeFunctionCall(std::forward<Functor>(p)))
{
}
R operator()(T arg, Arg&&... args)
{
return implementation->call(arg, args...);
}
};
你看 - 它需要有一个参数(自由函数的对象或第一个参数)。对于零参数函数,您可以对自由函数myfunction<R ()>
进行简单的特化。