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

时间:2016-08-02 04:49:49

标签: c++ c++11 macros c-preprocessor

我希望修改传递给宏的名称,以将其用作函数的名称。例如,我有一个名为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必须根据输入参数生成函数。

EDIT2:

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

#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_name的格式为Bar::fcn,我希望proper_fcn_name将其更改为Bar_fcn。在最后,如果some_nameBar::fcn

,我希望有这样的结果
void Bar_fcn(const stirng& name) { }
void Bar::fcn()
{
  Bar_fcn("Bar::fcn");
}

我必须提到Bar::fcn只是一个名字,但我必须考虑这个因为我的图书馆用户之前使用过这种风格。

2 个答案:

答案 0 :(得分:2)

我认为不应该强调你不应该这样做,这听起来像是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__(在这一堆之上还有一个更难看的黑客)。

答案 1 :(得分:1)

我对您的问题很感兴趣并做了以下示例:

#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

但遗憾的是我不知道如何(并且假设不可能)用其他字符替换::(例如_)。