C ++强制预处理器来评估数字

时间:2015-07-31 19:08:13

标签: c++ c-preprocessor

我正在编写一个C ++程序,我有预定义的对象Serial1,Serial2,Serial3等。我需要根据编译时已知的数字输入创建一个只对其中一个进行操作的函数。我使用连接宏#define SER(x) Serial##x,但在我的主要使用SER(port).read()并且port是等于1的int时,表达式扩展为Serialport.read()而不是Serial1.read()。但是,SER(1).read()会提供所需的结果。如何强制预处理器评估变量port并在扩展中使用其值?

顺便说一下,我不知道Serial1,Serial2等的类名,所以我无法使用指针或引用来设计变通方法

编辑:看到一些答案后,我需要补充一些说明。我需要能够在所有Seri​​al1,Serial2等中使用此函数,在我的代码的SINGLE RUN中多次调用它。很抱歉没有说清楚!

2 个答案:

答案 0 :(得分:2)

You need to use two levels of macros to accomplish what you are trying.

#define SER2(x) Serial##x
#define SER(x) SER2(x)

Here's a test program that demonstrates the concept.

#include <iostream>
#include <string>

struct Port
{
   Port(std::string name) : name_(name) {}

   void write()
   {
      std::cout << name_ << std::endl;
   }

   std::string name_;
};

Port Serial1("PORT1");
Port Serial2("PORT2");

#define SER2(x) Serial##x
#define SER(x) SER2(x)

int main()
{
   SER(port).write();
}

Command to build:

g++ -std=c++11 -Wall    socc.cc   -o socc -Dport=1

Output:

PORT1

Command to build:

g++ -std=c++11 -Wall    socc.cc   -o socc -Dport=2

Output:

PORT2

Update

With the updated question, the only sensible approach is to use an array of objects and use the appropriate element of the array based on the run time data.

答案 1 :(得分:2)

你不知道这种类型的事实并不重要:decltype(Serial1)会给出这一点。你知道他们是否都有相同的类型吗?因为如果他们不这样做,没有一个C ++函数可以直接返回它们。如果他们甚至没有共同的基类,那就更难了。

模板机制比预处理器更强大,因此草拟:

是有意义的
template<int N> struct Serial { };
template<> struct Serial<1> { static decltype(Serial1)* const ptr = &Serial1 };
template<> struct Serial<2> { static decltype(Serial2)* const ptr = &Serial3 };
template<> struct Serial<3> { static decltype(Serial3)* const ptr = &Serial3 };

// You can now use Serial<8/2-2>.ptr->

当然,写出模板专业化很无聊。让我们来看看Boost.PP:

#define BOOST_PP_LOCAL_MACRO (1, 7) // Assuming you have ports 1 to 7
#define BOOST_PP_LOCAL_MACRO(n) \
   template<> struct Serial<n> { \
       static decltype(BOOST_PP_CAT(Serial,n))* const ptr = &Serial##n; \
   };
#include BOOST_PP_LOCAL_ITERATE()

是的,最后一行是#include,没有引号。不,我不确定这是否有所改善;)