c ++宏将标记识别为参数

时间:2016-01-31 02:02:28

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

所以,已经有一段时间了,因为我用C ++编写任何东西,现在我正在使用C ++ 11和宏进行项目。

我知道通过使用stringify运算符,我可以这样做:

#define TEXT(a) #a    //expands to "a"

我应该如何使用预处理器来识别像+和*这样的标记来执行此操作:

#define TEXT(a)+ ???  //want to expand to "a+"
#define TEXT(a)* ???  //want to expand to "a*"

什么时候输入必须是那种语法?

我试过这样做:

#define + "+"

但当然它不起作用。如何让预处理器识别这些令牌?

注意: 这实际上是定义和使用正则表达式的小语言项目的一部分,其中生成的宏字符串将用于正则表达式。给出了语法,我们必须按原样使用它,而不对其进行任何更改。

例如 TEXT(a)+用于制作正则表达式:std::regex("a+") 不改变TEXT(a)扩展为" a"

的事实

4 个答案:

答案 0 :(得分:2)

首先,

#define TEXT(a) #a

没有“转换为"a"”。 a只是参数的名称。宏扩展为包含调用的TEXT的字符串。因此TEXT(42 + rand())将扩展为"42 + rand()"。请注意,如果将宏作为参数传递,则不会展开宏。 TEXT(EXIT_SUCCESS)将扩展为"EXIT_SUCCESS",而不是"0"。如果您想要完全展开,请添加一个额外的间接层,并将参数传递给TEXT到另一个执行字符串化的宏TEXT_R

#define TEXT_R(STUFF)   # STUFF
#define TEXT(STUFF)     TEXT_R(STUFF)

其次,我不太清楚您对TEXT(a)+TEXT(a)*的意思。您想要TEXT(foo)扩展为"foo+"吗?我认为在这种情况下最简单的解决方案是使用隐式字符串文字串联。

#define TEXT_PLUS(STUFF)  # STUFF "+"
#define TEXT_STAR(STUFF)  # STUFF "*"

或者,如果你想要完全扩展。

#define TEXT_R(STUFF)     # STUFF
#define TEXT_PLUS(STUFF)  TEXT_R(STUFF+)
#define TEXT_STAR(STUFF)  TEXT_R(STUFF*)

答案 1 :(得分:2)

您的作业无法在C ++中解决。您要么误解了某些内容,要么项目规范中存在错误。无论如何,我们在这里遇到了一个问题:

  

TEXT(a)+用于制作正则表达式:std::regex("a+") ,而不会更改TEXT(a)扩展为"a" 的事实[我的重点]

TEXT(a)扩展为"a" - 意思是,我们可以在示例中的任何地方替换TEXT(a);毕竟,这正是预处理器的作用。换句话说,您希望编译器转换此C ++代码

"a"+

std::regex("a+")

这根本不可能,因为C ++预处理不允许扩展+令牌。

我们在C ++中可以做的最好的事情是使用运算符重载来生成所需的代码。但是,有两个障碍:

  • 您只能在自定义类型上重载运算符,而"a"不是自定义类型;它的类型是char const[2](为什么2?空终止!)。

  • Postfix - +不是有效的C ++运算符,不能重载。

如果你的作业只是有点不同,那就行了。事实上,如果您的作业说TEXT(a)++应该产生所需的结果,并且您可以更改TEXT的定义以输出"a"以外的其他内容,那么我们就会经商:

#include <string>
#include <regex>

#define TEXT(a) my_regex_token(#a)

struct my_regex_token {
    std::string value;

    my_regex_token(std::string value) : value{value} {}

    // Implicit conversion to `std::regex` — to be handled with care.

    operator std::regex() const {
        return std::regex{value};
    }

    // Operators

    my_regex_token operator ++(int) const {
        return my_regex_token{value + "+"};
    }

    // more operators …
};

int main() {
    std::regex x = TEXT(a)++;
}

答案 2 :(得分:1)

您不希望将字符戳到宏的末尾。

也许你只是想要这样的东西:

#define TEXT(a, b) #a #b

那样TEXT(a, +)扩展为“a”“+”而TEXT(a, *)扩展为“a”“*”

如果您需要确切的语法,请使用辅助宏,例如:

#define TEXT(a) #a
#define ADDTEXT(x, y) TEXT(x ## y)
这样,ADDTEXT(a, +)扩展为“a +”,ADDTEXT(a, *)扩展为“a *”

答案 3 :(得分:0)

你也可以这样做:

#define TEXT(a) "+"  // "a" "+" -> "a+"
#define TEXT(a) "*"  // "a" "*" -> "a*"

C / C ++中的两个字符串文字将通过规范连接到单个文字中。