我想用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;
答案 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