gpt4 book ai didi

c++ - 可变参数模板匹配和 SFINAE?

转载 作者:塔克拉玛干 更新时间:2023-11-03 07:48:47 24 4
gpt4 key购买 nike

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的意思,我说的对吗?我把成员函数专业版二注释掉后,会和一版匹配,这是为什么呢?请帮助我。

最佳答案

正如评论中所指出的——这个特化正在接管你的一个 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级别应服务于所有 - 自由函数和成员函数 - 仅在特定对象实例的构造期间 - 您应通过参数类型选择“实现” - 如果它是成员函数或自由函数。

首先你必须定义任何函数调用抽象:

template<typename R, typename T, typename ... Args>
class AnyFunctionCall
{
public:
virtual ~AnyFunctionCall() {}

virtual R call(T arg, Arg&&... args) const = 0;
};

我看你已经知道如何为自由函数和成员函数实现这个接口(interface)了。

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 ()> .

关于c++ - 可变参数模板匹配和 SFINAE?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33183240/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com