使用C++预处理器定义多个类似的变量

kyb*_*kyb 0 c++ preprocessor

微控制器有许多引脚,每个引脚都定义为

const Leg PA29 { PIOA, BIT(29) };   // struct Pin is already taken
// ... about 120 more: 4 port x 32 pin
Run Code Online (Sandbox Code Playgroud)

define用简短的形式写了一个简单的别名

#define P(Port,PinN)  \
    const Leg P##Port##PinN { PIO##Port, BIT(PinN) }
Run Code Online (Sandbox Code Playgroud)

用它作为

P(D,2);  //produces PD2 with { PIOD, BIT(2) }
Run Code Online (Sandbox Code Playgroud)

尼斯.
现在我需要 - 不会P在4个端口上调用120次以上,每个端口有32个引脚.我想看到类似的东西

FOR_EACH( X in A,B,C,D ) \
  FOR_EACH( i in 0..31 ) \
    P(X,i);
Run Code Online (Sandbox Code Playgroud)

请不要建议TCL,python等生成C++代码.
我找到了答案,但要理解如何在我的案例中使用它是很复杂的.

主要思想是避免120行复制粘贴.所有120多个引脚应定义为大约10行.

UPD.如何BIT定义:

///@param n is value from 0 to number of bits in unsigned value
template<typename UnsignedIntegerT=unsigned>
constexpr UnsignedIntegerT BIT(UnsignedIntegerT n){ return 1<<n; }
Run Code Online (Sandbox Code Playgroud)

UPD2.最小的例子

///////////////////
// Vendor provides something like:
///////////////////

struct Pio
{
    unsigned reg1;
    unsigned reg2;
    unsigned reg3;
    //...
    unsigned regN;
};


// values not from datasheet but from lantern
#define PIOA  ((Pio*)0xAABB6789)
#define PIOB  ((Pio*)0xAABB2569)
#define PIOC  ((Pio*)0xAABB2566)
#define PIOD  ((Pio*)0xAABB2323)
//...



/////////////
// Kyb's code
/////////////

class Leg 
{
public:
    Pio *pio;
    unsigned pinN;
//methods...
};


///@param n is value from 0 to number of bits in unsigned value
template<typename UnsignedIntegerT=unsigned>
constexpr UnsignedIntegerT BIT(UnsignedIntegerT n){ return 1u<<n; }


//////////////
// Now need to define 120+ pins-legs

// like this
const Leg PA29 { PIOA, BIT(29) };

// or with shortener alias

/// Alias to shortly produce leg definition
/// Example: `P(A,2)` will define `PA2` with proper PIO and bit.
#define P(Port,PinN)  \
        const Leg P##Port##PinN { PIO##Port, BIT<unsigned>(PinN) }

//P(D,4);  //produces PD4
//P(C,3);
Run Code Online (Sandbox Code Playgroud)

Sto*_*ica 5

你没有发布一个真正的小例子.所以这是最好的猜测.但是如果你使用C++ 14,并且你的类型是constexpr可构造的,那么在我看来你应该尽可能地取消预处理器,并且只使用变量模板:

enum port {A, B, C, D};

template<port>
struct PIO_ID;
template<> struct PIO_ID<A>{ static constexpr auto value = PIOA; };
template<> struct PIO_ID<B>{ static constexpr auto value = PIOB; };
template<> struct PIO_ID<C>{ static constexpr auto value = PIOC; };
template<> struct PIO_ID<D>{ static constexpr auto value = PIOD; };

template<port P>
constexpr auto PIO = PIO_ID<P>::value;

template<port PORT, int PIN_NUM>
constexpr Leg P{ PIO<PORT> , BIT(PIN_NUM) };
Run Code Online (Sandbox Code Playgroud)

就是这样.现在您可以将这些常量引用为P<A, 0>,等等.