通过#defines迭代

时间:2014-10-22 05:48:28

标签: c++ c-preprocessor

我的应用程序中有一个配置文件,如下所示。这个配置需要在构建程序之前完成。

#define NO_OF_COLORS 8   

#define COLOR_RESPONCE_1 'R'
#define COLOR_RESPONCE_2 'G'
#define COLOR_RESPONCE_3 'B'
#define COLOR_RESPONCE_4 'M'
#define COLOR_RESPONCE_5 'C'
#define COLOR_RESPONCE_6 'Y'
#define COLOR_RESPONCE_7 'O'
#define COLOR_RESPONCE_8 'P'

在类中,我需要将这些值集添加到std :: vector中。有没有办法迭代这些定义。可能正在使用宏?

5 个答案:

答案 0 :(得分:2)

您可以使用Boost.Preprocessor库。它提供了模拟预处理器的控制结构和数据结构的宏。例如。你可以迭代你的颜色:

#include <iostream>
#include <boost/preprocessor.hpp>

#define NO_OF_COLORS 8

#define COLOR_RESPONCE_1 'R'
#define COLOR_RESPONCE_2 'G'
#define COLOR_RESPONCE_3 'B'
#define COLOR_RESPONCE_4 'M'
#define COLOR_RESPONCE_5 'C'
#define COLOR_RESPONCE_6 'Y'
#define COLOR_RESPONCE_7 'O'
#define COLOR_RESPONCE_8 'P'

#define PRINT_COLOR(z, x, _)                    \
  std::cout << BOOST_PP_CAT(COLOR_RESPONCE_, x) << std::endl;

int main()
{
  BOOST_PP_REPEAT_FROM_TO(1, NO_OF_COLORS, PRINT_COLOR, 0);
}

BOOST_PP_REPEAT_FROM_TO使用计数器模拟循环,PRINT_COLOR宏实现循环体。

我个人会在没有其他选择的情况下使用Boost.Preprocessor。它只模拟控制结构并具有许多限制(例如,在许多循环迭代中),调试预处理器代码并不比重模板代码简单。

关于样式的说明。虽然预处理器是从C继承的,并且是单独(也是条件)编译所必需的,但它与现代C ++不同,实际上即使对于98之前的C ++也是如此。如果您需要常量,您可以并且应该使用 const 枚举(或者使用枚举类更好)或 constexpr 。这些常量可以放在命名空间中以避免名称冲突,可以保证它们只能初始化一次( extern const )。

答案 1 :(得分:1)

你无法通过宏进行迭代。预处理器编译可能是多阶段的,但名称本身只能在第一遍(预处理)中解析。

如果你这样做会更好:

const char Colors[] = {'R','G','B','C','M','Y','O','P'};

然后使用sizeof(Colors) / sizeof(Colors[0])查找此数组中的元素数。使用循环迭代:

for(size_t index = 0; index < sizeof(Colors) / sizeof(Colors[0]); ++index)
{}

或者,如果您使用的是支持基于范围的for循环的C ++ 11编译器,您可以使用:

for(char color : Colors) 
{ 
   // Use 'color'
}

更简单:

for(auto color : Colors) 
{ 
   // Use 'color'
}

答案 2 :(得分:1)

为什么不将它们存储在std::string而不是std::vector

const std::string COLDATA = "RGBMCYOP";

您仍然可以像std::vector一样使用索引[]

来访问它
COLDATA[3]; // == 'M'

或者如果您仍想将其放在矢量中,您可以这样做:

const std::vector<char> COLDATAVEC(COLDATA.begin(), COLDATA.end());

如果您使用 C ++ 11 ,则可以在不使用std::vector的情况下将其放入std::string

const std::vector<char> COLDATAVEC = {'R', 'G', 'B', 'M', 'C', 'Y', 'O', 'P'};

答案 3 :(得分:1)

定义您自己的迭代机制(限于10次迭代):

#define ITER_0(MACRO, ACTION, DATA)
#define ITER_1(MACRO, ACTION, DATA) ITER_0(MACRO, ACTION, DATA) ACTION(MACRO##1, DATA)
#define ITER_2(MACRO, ACTION, DATA) ITER_1(MACRO, ACTION, DATA) ACTION(MACRO##2, DATA)
#define ITER_3(MACRO, ACTION, DATA) ITER_2(MACRO, ACTION, DATA) ACTION(MACRO##3, DATA)
#define ITER_4(MACRO, ACTION, DATA) ITER_3(MACRO, ACTION, DATA) ACTION(MACRO##4, DATA)
#define ITER_5(MACRO, ACTION, DATA) ITER_4(MACRO, ACTION, DATA) ACTION(MACRO##5, DATA)
#define ITER_6(MACRO, ACTION, DATA) ITER_5(MACRO, ACTION, DATA) ACTION(MACRO##6, DATA)
#define ITER_7(MACRO, ACTION, DATA) ITER_6(MACRO, ACTION, DATA) ACTION(MACRO##7, DATA)
#define ITER_8(MACRO, ACTION, DATA) ITER_7(MACRO, ACTION, DATA) ACTION(MACRO##8, DATA)
#define ITER_9(MACRO, ACTION, DATA) ITER_8(MACRO, ACTION, DATA) ACTION(MACRO##9, DATA)
#define ITER_10(MACRO, ACTION, DATA) ITER_9(MACRO, ACTION, DATA) ACTION(MACRO##10, DATA)

#define ITER_I(ITERS, MACRO, ACTION, DATA) ITER_##ITERS(MACRO, ACTION, DATA)
#define ITER(ITERS, MACRO, ACTION, DATA) ITER_I(ITERS, MACRO, ACTION, DATA)

定义将在每次迭代时调用的操作:

#define PRINT(MACRO, DATA) std::cout << MACRO; 
#define ADD_TO_VECTOR(MACRO, DATA) DATA.push_back(MACRO);

使用以下操作:

std::vector<char> v;
ITER(NO_OF_COLORS, COLOR_RESPONCE_, ADD_TO_VECTOR, v)

ITER(NO_OF_COLORS, COLOR_RESPONCE_, PRINT, ~)

DEMO

答案 4 :(得分:0)

似乎你想迭代一个枚举。 C ++不支持这一点(其他语言,例如Java在默认情况下确实有此行为。要解决此问题,您需要创建一个可迭代,长度恒定且定义良好的数据结构,因此很容易维护。

例如,您可以将数据存储在std::array(或c ++ 11之前std::tr1::array

const std::array<BYTE,8> Colors = { { 'R','G','B','C','M','Y','O','P' } };

std::array包含迭代器和size()运算符。所以你可以做到

for( std::array<BYTE,8>::const_iterator itr = Colors.begin();
     itr != Colors.end();
     ++itr )
{
    // use (*itr)
}

或者如果你想要索引

for( std::size_t index = 0 ; index < Colors.size() ; ++index )
{
    // use Colors[i]
}

并在c++11中您可以使用:

for( auto color : Colors )
{
     // use color     
} 

您也可以通过以下方式将其复制到std::vector

std::vector<BYTE> Colors_vector( Colors.begin(), Colors.end() );