转换宏参数名称以用作c++中的函数

Transform a macro parameter name to use as a function in c++

本文关键字:c++ 函数 参数 转换      更新时间:2023-10-16

我想修改传递给宏的名称,将其用作函数的名称。例如,我有一个名为foo的宏,如下所示:

#define foo(name) void name(const string& in) { \do something }

但我想用foo(Bar::do)这样的参数来调用这个宏,所以我必须将名称更改为合适的名称才能将其用作函数。

有什么方法可以实现这一点吗?我使用c++11和g++5.x.

编辑:

我遇到的问题是因为有一个旧版本的宏,它可以不受限制地使用,所以现在我的代码中有很多部分使用foo(Bar::do)之类的宏,但现在我必须使用这些名称生成一个函数,但函数名称必须与众不同,所以我决定使用宏输入参数作为函数名称,但我遇到了我解释的问题。

这是一个例子:

void Bar::do(some_parameters)
{
   FOO(Bar::do);
}

这是我以前的代码部分,现在我想在这部分上面添加第二个宏,如下所示:

FOO2(Bar::do)
void Bar::do(some_parameters)
{
  FOO(Bar::do);
}

两个名称必须相同,但FOO2必须根据输入参数生成一个函数。

第2版:

我试着在这里更准确地解释这个问题。以前,我有一个这样的宏:

#define FOO(name) 
   some codes here

但现在我希望有一个宏,能够扩展如下:

#define FOO2(name) void proper_fcn_name(name)(const string &name){ do the same thing here}
#define FOO(name) proper_fcn_name(name)(#name)

我可以这样使用:

FOO2(some_name)
void Bar::fcn()
{
  FOO(some_name); 
}

如果some_nameBar::fcn的格式,我希望proper_fcn_name将其更改为例如Bar_fcn。最后,如果some_nameBar::fcn:,我希望有这样的东西

void Bar_fcn(const stirng& name) { }
void Bar::fcn()
{
  Bar_fcn("Bar::fcn");
}

我必须提到Bar::fcn只是一个名称,但我必须考虑这一点,因为我的库用户以前使用过这种风格。

我对你的问题很感兴趣,并做了以下例子:

#include <iostream>
#include <string>
using namespace std;
#define foo(name) void name (const string& in) { cout << in << endl; }
// function with name bar_do
foo(bar_do)
// function with name bar_do
foo(do_bar)
int main(void)
{
    bar_do("The first test");
    do_bar("The second test");
}

事实上它是有效的(它是输出),

第一次测试

第二次测试

但我不明白你想从宏定义的奇怪用法中得到什么——现在看起来像是用不同名称生成相同函数的自动复制粘贴方法。

更新

如果您真的想使用名称空间(例如Bar),请考虑以下示例:

#include <iostream>
#include <string>
using namespace std;
#define foo(name) void name (const string& in) { cout << in << endl; }
namespace Bar{
    void func(const string& in);
}
foo(Bar::func)
int main(void)
{
    Bar::func("The special test");
}

您应该理解,名称空间必须定义,并且do是C++语言的关键字(所以,您不应该将其用作函数名)

更新2

如果可以将旧代码中的FOO(Bar::do);更改为FOO(Bar,do);,则可以进行简单的替换以生成用于调用和定义的Bar_do标识符:

#include <iostream>
#include <string>
using namespace std;
#define defgen(class_name,method_name) void class_name##_##method_name(const string& in) {  cout << in << endl; }
#define callgen(class_name,method_name,...) class_name##_##method_name(__VA_ARGS__);
// produses definition
defgen(Bar,do)
int main(void)
{
    // produces call with particular value as an argument
    callgen(Bar,do,"The call test");
}

kfsone说(在评论你的问题):

MYMACRO(A::b)可能产生A_b_stub

但不幸的是,我不知道如何(并且假设这是不可能的)用其他字符(例如_)来替换CCD_。

我认为不应该这样做,这听起来像是XY问题。

你可能应该完整地解释这个问题,你为什么要尝试生成这个函数,它是如何使用的,等等

不管怎样,说教够了,这里有一个解决方案:

#include <iostream>
#include <map>
#include <string>
#include <functional>
std::map<std::string, std::function<void(const std::string&)>> g_functions;
#define FOO(name) static void* nonsense##__COUNTER__ =                
                  (void*)&(  g_functions[ #name ] =                   
                   [](const std::string& in)                           
                  {                                                   
                    std::cout << "generated function for : " << #name  
                              << " called with arg:" << in << std::endl;  
                  });
#define FOO2(name) {g_functions[ #name ](#name); }
namespace Bar
{
    FOO(Bar::func)
    void func()
    {
        FOO2(Bar::func);
    }
}
int main() {
    Bar::func();
    return 0;
}

如果你的编译器没有__COUNTER__,你可以在大多数时候使用__LINE__(这是一堆丑陋的破解)。