如何使用Boost预处理器扩展字符串

时间:2014-12-22 13:43:56

标签: c++ boost recursion macros boost-preprocessor

我想用Boost的预处理器库扩展一个未知长度的字符串。

例如我想要这个:

const string foo{"bar"};

由我的宏扩展到:

  

foo [0],foo [1],foo [2],' \ 0'

这是我的代码,我大部分都是从here复制的:

#include <boost/preprocessor/arithmetic/add.hpp>
#include <boost/preprocessor/arithmetic/inc.hpp>
#include <boost/preprocessor/arithmetic/sub.hpp>
#include <boost/preprocessor/control/deduce_d.hpp>
#include <boost/preprocessor/repetition/repeat.hpp>
#include <boost/preprocessor/tuple/elem.hpp>

#define EXPAND(first, last) BOOST_PP_REPEAT( BOOST_PP_INC( BOOST_PP_SUB((last), (first)), EXPAND_M, ((first), BOOST_DEDUCE_D())), '\0'

#define EXPAND_M(z, n, data) EXPAND_M_2((n), BOOST_PP_TUPLE_ELEM(2, 0, (data)), BOOST_PP_TUPLE_ELEM(2, 1, (data)))

#define EXPAND_M_2(n, first, d) foo[BOOST_PP_ADD_D((d), (n), (first))],

我可以像这样使用它吗?

const string foo{"bar"};

cout << string{ EXPAND(0, foo.size()) } << endl;

2 个答案:

答案 0 :(得分:3)

由于预处理器仅适用于令牌,因此您必须提供传递给foo的字符串的长度作为硬编码的魔术常量,即整数字面值。没有办法解决这个问题。
由于这个整数文字与字符串文字无关,因此整个方法容易出错,应该避免使用。

如果您正在寻找灵活的扩展,请尝试使用可变参数模板。 (很难说你应该使用什么,因为你没有提供你需要的用例!)

答案 1 :(得分:3)

您是否只想找到一种方法来包含(尾随)NUL角色?

#include <algorithm>
#include <iterator>
#include <iostream>
#include <sstream>

template <typename R = std::string, size_t N>
R stringlit(char const(&lit)[N]) {
    return R(lit+0, lit+N);
}

static std::string const foo(stringlit("bar"));
static auto        const bar(stringlit<std::vector<int>>("bar"));

int main() { 
    std::cout << "foo: ";
    for(char ch : bar)
        std::cout << std::showbase << std::hex << static_cast<int>(ch) << " ";

    std::cout << "\nbar: ";
    for(int i : bar)
        std::cout << std::showbase << std::hex << i << " ";
}

打印

foo: 0x62 0x61 0x72 0 
bar: 0x62 0x61 0x72 0 

也许相关的变化:

您还可以使用模板别名来明确指定数组文字的大小:

template <typename T> using Alias = T;

static std::string const foo(stringlit(Alias<char[7]>{"bar"})); // 4 trailing '\0's