C++ 使用预处理器从f(列表)中删除参数列表

C++ 使用预处理器从f(列表)中删除参数列表,c++,c-preprocessor,C++,C Preprocessor,在我看来,我在boost库中看到了一些奇怪的事情,而这正是我现在想要做的。但是找不到它 我想创建一个宏,该宏接受签名并将其转换为函数指针: void f(int,int) {} ... void (*x)(int,int) = WHAT( (f(int,int)) ); x(2,4); // calls f() 我特别需要它来处理成员函数指针,以便使用两个参数: WHAT(ClassType, (f(int,int)); // results in static_cast<void

在我看来,我在boost库中看到了一些奇怪的事情,而这正是我现在想要做的。但是找不到它

我想创建一个宏,该宏接受签名并将其转换为函数指针:

void f(int,int) {}

...
void (*x)(int,int) = WHAT( (f(int,int)) );

x(2,4); // calls f()
我特别需要它来处理成员函数指针,以便使用两个参数:

WHAT(ClassType, (f(int,int)); // results in static_cast<void (ClassType::*)(int,int)>(&ClassType::f)
WHAT(ClassType,(f(int,int));//导致静态转换(&ClassType::f)
为了解决我的问题,这不是绝对必要的,但它会让事情变得更美好


这个问题本身与函数指针无关。需要做的是使用预处理器将“f(int,int)”转换为两个不同的部分:

“f” "(int,int)"


原因:

我已经解决了这里提出的问题:

我已经开始了一系列文章来解释如何做到这一点:

签名必须根据用户试图连接的“信号”求值并精确匹配。Qt用户习惯于将其表示为
signal(fun(param,param))
,因此类似
connect\u static(SIGINFO(object,fun(param,param)),[](int,int){}的东西不会觉得太奇怪


为了构造签名,我需要能够从提供的参数中提取它。有足够的信息来获取成员函数地址(使用C++0x的decltype)并获取签名以生成适当的包装器,但我看不到如何提取它。我能想到的最接近的是
SIGINFO(object,fun,(param,param))
,这可能已经足够好了,但我想在考虑不可能得到我想要的确切语法之前,我应该先问一下。

不幸的是,使用标准的预处理器,你想做什么是不可能的。原因有两个:

  • 无法使用自定义字符分割传递给宏的参数。这些参数必须以逗号分隔。否则,问题会立即得到解决
  • 您不能使用预处理器来定义非标识符的内容。否则,您可以使用双扩展,其中
    被定义为
    ,并在其上拆分参数,就像它作为
    f,int,int,
    传递一样,然后将其作为可变参数处理
  • C++中的函数指针定义不允许您推断给定类型的名称,不幸的是。
更进一步地说,即使您设法创建了一个函数指针,代码也不能用于方法,因为为了调用一个方法,您需要有两个指针——指向方法的指针和指向类实例的指针。这意味着您必须在这些东西周围有一些包装器

这就是为什么QT使用自己的工具,如
moc
来生成粘合代码

在Boost中,您可能看到的是信号库、绑定库和Lambda库。具有讽刺意味的是,这些库比您试图实现的功能强大得多,但同时它们不允许您以您想要的方式实现它。例如,即使您可以用您想要的语法实现您想要的功能,您也可以使用在上,如果信号具有不同的签名,则无法将插槽“连接”到“信号”。同时,我上面提到的Boost库完全允许这样做。例如,如果您的“插槽”需要的参数多于“信号”提供的参数,则可以在“插槽”时绑定要传递的其他对象如果“slot”不需要额外的参数,则这些库也可以抑制这些参数

<>我想从C++到现在的最好方法是使用Boost信号方法在GUI库中实现事件处理。Qt不使用它有很多原因。首先,它开始时就像90-s,当C++不是那么新奇的时候。此外,为了解析“时隙”和“信号”,它们必须解析代码。在平面设计师

对我来说,似乎不是使用宏,甚至更糟的是——C++上的非标准工具来生成代码,并使用以下内容:

void (*x)(int,int) = WHAT( (f(int,int)) );
这样做会更好:

void f (int x, int y, int z);
boost::function<void (int, int)> x = boost::bind (&f, _1, _2, 3);
x (1, 2);
void f(int x,int y,int z);
boost::function x=boost::bind(&f,_1,_2,3);
x(1,2);

上面提到的函数和方法都适用。

Hmm,我最初误解了……所以它需要明确的参数“(f(int,int))”-这些是以某种方式生成的吗?好问题,我曾经也有过类似的要求。正在等待答案。您可以使用
boost::function\u traits
boost::function\u types::parameter\u types
解决这个问题,但是,我不确定它是否满足预处理器的规定。不会工作。它发生在错误的位置时间。为了得到函数的特征,我必须把'f(int,int)调成'转换为函数指针。为了做到这一点,我需要单独使用'f'。函数特性肯定会发挥作用,但首先我需要拆分这个源字符串,我能想到的唯一方法是预处理器。我认为我没有看到类似的情况。预处理器绝对没有处理参数的能力。据我所知,boost只分解了括号内的子列表。