1

我正在编写一些宏,它们采用函数名称并执行一些操作,其中之一是通过它的签名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它只接受参数列表(如果它是带有返回类型的完整签名,那将是微不足道的),以便选择正确的成员函数重载。

4

2 回答 2

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);
于 2012-05-01T13:26:42.573 回答
1

使用decltype并拨打电话表达式:decltype(f(0, 0, 0)). 当参数是您不能轻易提供 (unlike int) 的实例的类型时,使用std::declval来伪造它:

decltype(f(std::declval<int>(), std::declval<int>(), std::declval<int>()))
于 2012-04-29T22:24:26.877 回答