我正在编写一些带有函数名称并执行某些操作的宏,其中一个是通过decltype
获取其签名并将其用作模板参数。
我想扩展这些宏以支持重载函数。我的想法是让它们采用额外的参数来指定参数列表而不是完整的签名,因为两个函数重载只能对返回类型不同。当我尝试重建函数的完整签名时出现问题,正如我在decltype
的非重载情况下所做的那样:我如何猜测返回类型?
我尝试了result_of
,但没有运气:
#include <type_traits>
#include <typeinfo>
#include <iostream>
using namespace std;
double f(int, int);
int f(int, int, int);
int main(){
cout<<typeid(result_of<decltype(&f)(int,int, int)>::type).name()<<endl;
}
如果double f(int, int)
已被注释,则该代码段有效。我知道这是因为在decltype
内不知道要选择哪两个重载。通常情况下,人们可以在与所需重载相匹配的签名前添加一个虚拟强制转换,但这意味着您事先知道返回类型,因此所有这些东西都是无用的。
有没有办法解决这个问题,还是我必须强制用户在宏中指定完整的签名?
编辑: 基本上,我有这两个宏:
//add a member function as a method
#define addmethod2(stringname, methodname) fields[#stringname]=method_helper<decltype(&hold_type::methodname), &hold_type::methodname>::worker
#define addmethod(methodname) addmethod2(methodname, methodname)
我想添加第三个addmethod3
,它只使用 参数列表(如果它是带有返回类型的完整签名,那将是微不足道的),以便选择正确的成员函数重载。
答案 0 :(得分:2)
怎么样?
template<typename T>
struct identity { typedef T type; };
template<typename T>
using NoDeduce = typename identity<T>::type;
template<typename T>
using Identity = T;
template<typename ...P, typename R>
Identity<R(P...)> *get_f(R f(NoDeduce<P>...)) {
return f;
}
然后你可以说
auto *f1 = get_f<int, int, int>(f);
auto *f2 = get_f<int, int>(f);
答案 1 :(得分:1)
使用decltype
并拨打电话:decltype(f(0, 0, 0))
。如果参数是您无法轻松提供实例的类型(与int
不同),请使用std::declval
伪造它:
decltype(f(std::declval<int>(), std::declval<int>(), std::declval<int>()))