通过提升阻止意外的宏重新扩展?

时间:2017-09-24 08:06:40

标签: c++ boost

此处的目标是简单地将abc取出而不是实际值。设置“足够简单”:

#include <boost/preprocessor/seq/for_each_i.hpp>
#include <boost/preprocessor/seq/for_each.hpp>
#include <boost/preprocessor/stringize.hpp>
#include <iostream>

// Define "invalid" sequence first
#define SEQ (a)(b)(c)

// Try to create "final" value with `std::string("elem")`
// Brought in for explicit `std::string`, but no dice
#define MAKE_XSTRING(x) MAKE_STRING(x)
#define MAKE_STRING(x)  std::string(#x)

// oh, the humanity!             vvvvvvvvvvvv or BOOST_PP_STRINGIZE
#define HUMANIZE(r, data, elem) (MAKE_XSTRING(elem))
#define SEQ_HUMAN BOOST_PP_SEQ_FOR_EACH(HUMANIZE,,SEQ)

所以我现在所期待的就是我所拥有的:带有(std::string("a"))等的新序列:

// confirmation:     vvvvvvvvvvvvvvvv
// warning: Humans: (std::string("a")) (std::string("b")) (std::string("c"))
#pragma message "Humans: " BOOST_PP_STRINGIZE(SEQ_HUMAN)

认为我非常聪明并且已经在一些显式字符串中整理了我的值,现在我定义了“真实”代码所需的实际值。

// Now that we have the "final" values, actually define the real values
// in real code, it's some lengthy nested namespaces (inconvenient to type)
#define a 123
#define b 456
#define c 789

最后,让我们打印它们以确保它们不会展开:

// Let there be printing!
#define GOTTA_PRINT_EM_ALL(r,data,i,elem) << ((i)+1) << ". " << elem << std::endl

int main(int argc, const char **argv) {
    std::cout << "Humans: " << std::endl
        BOOST_PP_SEQ_FOR_EACH_I(GOTTA_PRINT_EM_ALL,,SEQ_HUMAN);
}

但似乎外星人确实接管了:

Humans:
1. 123
2. 456
3. 789

鉴于他们应该是std::string("a") ......真正的价值回到那里是多么的糟糕?!我想也许("a")构造函数中的std::string正在创建问题,但似乎并非如此(BOOST_PP_STRINGIZE导致相同的行为)。有什么建议吗?

1 个答案:

答案 0 :(得分:1)

宏确实扩展为代码令牌

test.cpp|24 col 1| note: #pragma message: Humans: (std::string("123")) (std::string("456")) (std::string("789"))

现在,当您将代码令牌插入GOTTA_PRINT_EM_ALL宏时,您将获得

<< ((0)+1) << ". " << std::string(\"123\") << std::endl << ((1)+1) << ". " << std::string(\"456\") << std::endl << ((2)+1) << ".  << std::string(\"789\")" << std::endl

完全有望打印

Humans: 
1. 123
2. 456
3. 789

获取&#34;代码令牌&#34;你还需要 stringize

// Let there be printing!
#define GOTTA_PRINT_EM_ALL(r,data,i,elem) << ((i)+1) << ". " << BOOST_PP_STRINGIZE(elem) << std::endl

打印

Humans: 
1. std::string("123")
2. std::string("456")
3. std::string("789")

查看 Live On Coliru

#include <boost/preprocessor/seq/for_each_i.hpp>
#include <boost/preprocessor/seq/for_each.hpp>
#include <boost/preprocessor/stringize.hpp>
#include <iostream>
#include <string>

#define a 123
#define b 456
#define c 789
#define SEQ (a)(b)(c)

// Try to create "final" value with `std::string("elem")`
// Brought in for explicit `std::string`, but no dice
#define MAKE_STRING(x)  std::string(#x)
#define MAKE_XSTRING(x) MAKE_STRING(x)

#define HUMANIZE(r, data, elem) (MAKE_XSTRING(elem))
#define SEQ_HUMAN BOOST_PP_SEQ_FOR_EACH(HUMANIZE,,SEQ)

// Let there be printing!
#define GOTTA_PRINT_EM_ALL(r,data,i,elem) << ((i)+1) << ". " << BOOST_PP_STRINGIZE(elem) << std::endl

int main() {
    std::cout << "Humans: " << std::endl
        BOOST_PP_SEQ_FOR_EACH_I(GOTTA_PRINT_EM_ALL,,SEQ_HUMAN);
}