Is there an easy way for an iterator over a static list of strings in C ++

It often happens that I need to iterate over a list of strings in my C ++ code.

In languages ​​like Perl, this is easy:

foreach my $x ("abc", "xyz", "123") {.... }

In the past, this is what I have done in C ++

const char* strs[] = { "abc", "xyz", "123" };
for (int i=0; i<sizeof(strs)/sizeof(const char*); i++) {
   const char *str = strs[i];
   ...

If I already have an STL container, I can use BOOST_FOREACH

std::vector<std::string> strs;
BOOST_FOREACH(std::string str, strs) {
   ...

I tried to create a macro to combine all these concepts, but to no avail.

I would like to be able to write code as follows:

SPECIAL_STRING_FOREACH(const char* str, {"abc", "xyz", "123"}) {
   ...
}

Surely someone had prepared this before.

+3
source share
8 answers

Here is my attempt. Unfortunately, it relies on variable macros, which are functions of C99 / C ++ 1x. But it works at 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;
    }
}

, , . 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;
    }
}

, , . boost::remove_reference . boost::decay. , , , . .

, , , typename boost::remove_reference boost::function_traits. SEQ_FOR_EACH_D (D == ).

+9

, C , :

const char* strs[] = { "abc", "xyz", "123", NULL };
for (int i=0; strs[i] != NULL  i++) {
  ...
}
+5

- :


void func( const char* s ) { /* ... */ }

const char* array[] = { "abc", "xyz", "123" };
std::for_each( array, array + 3, func );

boost::array.

+4

Cou va_arg , , ( , !)

++- (++ 0x) ( )

- boost::assignment FOREACH.

, BOOST::FOREACH !

+2

, , .

#define N_ELEMS(a) (sizeof(a) / sizeof((a)[0]))

.

for(int i = 0; i < N_ELEMS(strs); ++i) {
  ...
}

, .

+1

:

for (int i=0; i<sizeof(strs)/sizeof(const char*); i++)
{
    const char *str = strs[i];
    ...

:

for (const char *ptr = strs[0],
    *end = strs[sizeof(strs)/sizeof(const char*)];
    ptr < end; ++ptr)
{
    ...

-ize; ptr .

- .

, . for (, ), .

0

( , )

#define STR_ARRAY_FOREACH(I) const char* Items[] = I; for( const char *item = Items[0], *end = strs[ sizeof( Items ) / sizeof( const char* ) ]; item < end; ++item )

:

STR_ARRAY_FOREACH({ "abc", "xyz", "123" })
{
    cout << item << "\n";
}
0

I would try just using BOOST_FOREACH in the array directly. the documentation seems to think this will work.

Actually it is. It should be two lines, but it works:

const char * myarray[] = {"abc", "xyz", "123"};
BOOST_FOREACH (const char *str, myarray) {
  std::cout << "Hello " << str << std::endl;
}
0
source

Source: https://habr.com/ru/post/1708910/


All Articles