c++强制预处理器计算一个数字

C++ Force preprocessor to evaluate a number

本文关键字:一个 数字 计算 预处理 处理器 c++      更新时间:2023-10-16

我正在写一个c++程序,我有预定义的对象Serial1, Serial2, Serial3等。我需要使一个函数只对其中一个操作,这取决于在编译时已知的数字输入。我使用连接宏#define SER(x) Serial##x,但在我的主要,如果使用SER(port).read()和端口是一个int等于1,表达式扩展到Serialport.read()而不是Serial1.read()。然而,SER(1).read()给出了所需的结果。我怎样才能强制预处理器评估变量port并在扩展中使用其值?

顺便说一句,我不知道Serial1, Serial2等的类名,所以我不能使用指针或引用设计一个解决方案

编辑:在看到一些答案后,我需要添加一些澄清。我需要能够使用这个函数与所有Serial1, Serial2等通过调用它多次在我的代码的单次运行。抱歉之前没有说清楚!

您需要使用两级宏来完成您正在尝试的任务。

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

下面是演示这个概念的测试程序。

#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();
}

构建命令:

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

PORT1

构建命令:

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

PORT2

对于更新后的问题,唯一合理的方法是使用对象数组,并根据运行时数据使用数组中的适当元素。

你不知道类型的事实并不重要: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。不,我不确定这是否是一个改进;)