mmc*_*coo 3 c++ string iterator
我经常需要迭代我的C++代码中的字符串列表.
在像Perl这样的语言中,这很容易:
foreach my $x ("abc", "xyz", "123") {.... }
Run Code Online (Sandbox Code Playgroud)
过去,这就是我在C++中所做的
const char* strs[] = { "abc", "xyz", "123" };
for (int i=0; i<sizeof(strs)/sizeof(const char*); i++) {
const char *str = strs[i];
...
Run Code Online (Sandbox Code Playgroud)
如果我已经有一个STL容器,我可以使用BOOST_FOREACH
std::vector<std::string> strs;
BOOST_FOREACH(std::string str, strs) {
...
Run Code Online (Sandbox Code Playgroud)
我试图创建一个宏来结合所有这些概念,但没有成功.
我希望能够编写这样的代码:
SPECIAL_STRING_FOREACH(const char* str, {"abc", "xyz", "123"}) {
...
}
Run Code Online (Sandbox Code Playgroud)
肯定有人以前做过这个.
这是我的尝试.遗憾的是,它依赖于可变宏,这是一个C99/C++ 1x功能.但是在GCC工作.
#include <boost/foreach.hpp>
#include <boost/type_traits.hpp>
#include <iostream>
#define SEQ_FOR_EACH(D, ...) \
if(bool c = false) ; else \
for(boost::remove_reference<boost::function_traits<void(D)> \
::arg1_type>::type _t[] = __VA_ARGS__; \
!c; c = true) \
BOOST_FOREACH(D, _t)
int main() {
SEQ_FOR_EACH(std::string &v, { "hello", "doctor" }) {
std::cout << v << std::endl;
}
}
Run Code Online (Sandbox Code Playgroud)
请注意,您还可以使用引用变量进行迭代,以避免无用的复制.这是一个使用boost.preprocessor和(a)(b)...语法,在预处理阶段后编译为相同的代码.
#define SEQ_FOR_EACH(D, SEQ) \
if(bool c = false) ; else \
for(boost::remove_reference<boost::function_traits<void(D)> \
::arg1_type>::type _t[] = { BOOST_PP_SEQ_ENUM(SEQ) }; \
!c; c = true) \
BOOST_FOREACH(D, _t)
int main() {
SEQ_FOR_EACH(std::string &v, ("hello")("doctor")) {
std::cout << v << std::endl;
}
}
Run Code Online (Sandbox Code Playgroud)
诀窍是组合一个函数类型,该函数类型具有枚举变量作为参数,并获取该参数的类型.然后boost::remove_reference将删除任何引用.使用第一个版本boost::decay.但它也会将数组转换为指针,我发现它有时并不是我想要的.然后将结果类型用作数组元素类型.
要在枚举器变量具有依赖类型的模板中使用,您必须使用另一个放在typenamebefore boost::remove_reference和之前的宏boost::function_traits.可以命名SEQ_FOR_EACH_D(D ==依赖).
小智 6
请注意,如果标记数组的末尾,则更容易处理字符串的C数组:
const char* strs[] = { "abc", "xyz", "123", NULL };
for (int i=0; strs[i] != NULL i++) {
...
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
3178 次 |
| 最近记录: |