如何定义一个定义调用自身的函数的宏?

Tim*_*ney 3 c++ macros c-preprocessor

我想创建一个宏来定义一个在对象列表上调用该函数的函数.它不一定必须是预处理器宏,但它应该工作.

我想写这样的东西:

CALL_ON_ALL(doSomething(int arg1, bool arg2))
Run Code Online (Sandbox Code Playgroud)

我想要它产生这个:

void doSomething(int arg1, bool arg2) {
    for (int i = 0; i < delegates.size(); i++)
        delegates[i]->doSomething(arg1, arg2);
}
Run Code Online (Sandbox Code Playgroud)

我有一些有用的东西:

#define CALL_ON_ALL(defSig, callSig) \
void defSig { \
    for (int i = 0; i < delegates.size(); i++) \
        delegates[i]->callSig; \
}
Run Code Online (Sandbox Code Playgroud)

问题是我必须分别编写定义签名和调用签名,如下所示:

CALL_ON_ALL(doSomething(int arg1, bool arg2), doSomething(arg1, arg2))
Run Code Online (Sandbox Code Playgroud)

有一个更好的方法吗?

编辑

它不一定必须是预处理器宏.任何有效的方法都可以.

Lin*_*ios 6

尝试使用单独的参数(对于两个参数)进行签名:

#define CALL_ON_ALL2(name, argType1, argName1, argType2, argName2) \
void name( argType1 argName1 , argType2 argName2 ) { \
    for (int i = 0; i < delegates.size(); i++) \
        delegates[0]->name( argName1 , argName2 ); \
}
Run Code Online (Sandbox Code Playgroud)

您可以将其复制为其他参数编号.


lee*_*mes 5

这是高阶函数的一个很好的例子,它是将另一个函数作为参数的函数.在这种情况下,要在每个元素上调用函数.

下面定义了一个调用f每个元素的高阶函数.它需要C++ 11用于可变参数模板(args...).如果您没有可用的C++ 11,则可以删除typename ...Args函数签名中的固定参数类型并使用它.

template<typename Delegates, typename Function, typename... Args>
void callOnAll(Delegates delegates, Function f, Args... args) {
    for (int i = 0; i < delegates.size(); i++)
        f(delegates[i], args...);
}
Run Code Online (Sandbox Code Playgroud)

现在您可以使用以下语法调用它:

callOnAll(delegates, std::mem_fun<void,Delegate>(&Delegate::doSomething), 42);
Run Code Online (Sandbox Code Playgroud)

std::mem_fun事件为您要为每个委托调用的成员函数创建一个临时函数对象.您还可以应用其他函数,将指针作为其第一个参数.例如,这个小的lambda函数(也仅限于C++ 11):

callOnAll(delegates, [](Delegate *d){
    d->doSomething(42);
});
Run Code Online (Sandbox Code Playgroud)

这几乎是一样的,只是另一种语法.

在这里查看示例:


这个代码略有不同的版本使用基于范围而不是基于索引的for循环,它看起来更清晰(也需要C++ 11):

template<typename Delegates, typename Function, typename... Args>
void callOnAll(Delegates delegates, Function f, Args... args) {
    for(auto d : delegates)
        f(d, args...);
}
Run Code Online (Sandbox Code Playgroud)

对于你的信息,有std::for_each几个你想要的东西,但是稍微更功能一些,因为它本身不需要函数参数,但是你提供了一个lambda函数/函子,它只接受一个指针实例.使用lambda函数将以下代码与上面的代码进行比较:

std::for_each(delegates.begin(), delegates.end(), [](Delegate *d){
    d->doSomething(42);
});
Run Code Online (Sandbox Code Playgroud)

唯一的区别是我们必须传递.begin().end()迭代器而不是只有一个容器实例,比如delegates.但是,标准库中定义了许多其他算法值得关注!