Arduino类中static_assert校验引脚参数失败的实现方案咨询
Arduino AnalogOutput类编译期引脚合法性校验问题
初始实现与编译错误
为了在传入错误引脚号时触发编译错误,最初编写的代码如下:
class AnalogOutput : public AnalogBlock { public: AnalogOutput(uint8_t _pin) : pin(_pin) { static_assert( pin == 3 || pin == 5 || pin == 6 || pin == 9 || pin == 10 || pin == 11, "INVALID PWM PIN USED" ); } void run() { if(IN2 != prevIn) { prevIn = IN2; // 输入变化时更新PWM电平 analogWrite(pin, IN2); } } private: const uint8_t pin; uint8_t prevIn; };
构造对象时传入编译时常量:
static ServoMotor M1 = ServoMotor(3); // 3为引脚号
但出现编译错误:
error: non-constant condition for static assertion static_assert ( ^~~~~~~~~~~~~ error: use of 'this' in a constant expression
模板类尝试与新错误
尝试将类改为模板类:
template<uint8_t pin> class AnalogOutput : public AnalogBlock { public: AnalogOutput(uint8_t _pin) : pin(_pin) { static_assert( pin == 3 || pin == 5 || pin == 6 || pin == 9 || pin == 10 || pin == 11, "INVALID PWM PIN USED" ); } void run() { if(IN2 != prevIn) { prevIn = IN2; // 输入变化时更新PWM电平 analogWrite(pin, IN2); } } private: const uint8_t pin; uint8_t prevIn; };
构造对象时:
static AnalogOutput a1 = AnalogOutput(0);
出现新错误:
error: invalid use of template-name 'AnalogOutput' without an argument list static AnalogOutput a1 = AnalogOutput(0) ;
附带提示:
note: class template argument deduction is only available with -std=c++1z or -std=gnu++1z note: 'template<unsigned char pin> class AnalogOutput' declared here class AnalogOutput : public AnalogBlock ^~~~~~~~~~~~
使用avr-gcc编译。
咨询问题
- 该需求是否可实现?
- 若可实现,正确方式是什么?
解决方案
1. 需求可实现
通过模板非类型参数可以实现编译期校验引脚合法性,因为模板参数是编译期常量,能被static_assert正确识别。
2. 正确实现方式
修改模板类,直接用模板参数传递引脚号,无需在构造函数中重复传参,也无需存储成员变量pin:
#include <Arduino.h> template<uint8_t pin> class AnalogOutput : public AnalogBlock { public: AnalogOutput() : prevIn(0) { // 编译期校验引脚合法性 static_assert( pin == 3 || pin == 5 || pin == 6 || pin == 9 || pin == 10 || pin == 11, "INVALID PWM PIN USED: Only pins 3,5,6,9,10,11 support PWM on AVR" ); } void run() { if(IN2 != prevIn) { prevIn = IN2; analogWrite(pin, IN2); } } private: uint8_t prevIn; };
3. 正确构造对象
直接通过模板参数指定引脚号,无需向构造函数传参:
static AnalogOutput<3> M1; // 合法引脚,编译通过 // static AnalogOutput<2> M2; // 非法引脚,编译时触发static_assert错误
关键说明
- 模板参数
pin是编译期常量,满足static_assert对常量表达式的要求,能在编译阶段直接校验引脚合法性。 - 无需存储
pin成员变量,直接使用模板参数即可,节省内存空间。 - 该写法兼容C11及以上标准,avr-gcc默认支持(无需额外开启C17)。
- 若坚持使用构造函数传参并触发类模板推导,需在编译时添加
-std=c++17或-std=gnu++17选项,但模板参数直接指定的方式更直观,编译期校验更可靠。
内容的提问来源于stack exchange,提问作者bask185
相关产品推荐
相关产品推荐

