我希望修改传递给宏的名称,以将其用作函数的名称。例如,我有一个名为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_name
是Bar::fcn
:
void Bar_fcn(const stirng& name) { }
void Bar::fcn()
{
Bar_fcn("Bar::fcn");
}
我必须提到Bar::fcn
只是一个名字,但我必须考虑这个因为我的图书馆用户之前使用过这种风格。
答案 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
但遗憾的是我不知道如何(并且假设不可能)用其他字符替换::
(例如_
)。