实例化带默认函数与存储键的可空值成员时遇类型说明符错误
修复C++类成员实例化时的「expected type specifier」编译错误
我想要实现一种可空值类型,它既支持传入默认值生成函数,又能通过指定的键从闪存中读取可能存在的自定义值。但在类中把它作为成员实例化时,传入的两个参数触发了「expected type specifier」编译错误,该怎么修复?
类中成员初始化的错误代码
class BatteryConfig { static float _defaultPackL1Undervoltage(); FloatStorageNullableWithDefault packL1Undervoltage("PackL1UndervoltageKey", _defaultPackL1Undervoltage); // <<<<== 错误发生在这里 };
相关基类实现代码
template <typename T> class Nullable { public: Nullable() : hasValue_(false) {} Nullable(const T& value) : hasValue_(true), value_(value) {} bool hasValue() const { return hasValue_; } virtual T get() const { if (!hasValue_) { throw std::runtime_error("Nullable value is not set"); } return value_; } virtual void set(const T& value) { hasValue_ = true; value_ = value; } protected: bool hasValue_; T value_; }; template <typename T> class NullableWithDefault : public Nullable<T> { public: NullableWithDefault(const std::function<T()>& defaultValue) : Nullable<T>(), defaultValue_(defaultValue) {} T get() const override { if (!Nullable<T>::hasValue_) { return defaultValue_(); } return Nullable<T>::get(); } protected: std::function<T()> defaultValue_; }; class FloatStorageNullableWithDefault : public NullableWithDefault<float> { public: FloatStorageNullableWithDefault( const std::string& key, const std::function<float()>& defaultValue ) : NullableWithDefault<float>(defaultValue), key_(key) {} /// returns the key std::string getKey() const { return key_; } private: const std::string key_; };
修复方案
方案1:在构造函数的成员初始化列表中初始化
将成员变量的初始化逻辑移到类的构造函数里,这是最稳妥的解决方式,避免类声明阶段的解析歧义:
class BatteryConfig { static float _defaultPackL1Undervoltage(); FloatStorageNullableWithDefault packL1Undervoltage; public: BatteryConfig() : packL1Undervoltage("PackL1UndervoltageKey", _defaultPackL1Undervoltage) {} };
方案2:显式转换为std::function<float()>
如果坚持就地初始化,显式把静态函数包装成std::function类型,消除隐式转换的不确定性:
class BatteryConfig { static float _defaultPackL1Undervoltage(); FloatStorageNullableWithDefault packL1Undervoltage( "PackL1UndervoltageKey", std::function<float()>(_defaultPackL1Undervoltage) ); };
注意:该方式要求编译器支持C++11及以上版本的就地初始化语法。
方案3:使用静态成员变量的类外初始化
如果该成员不需要每个实例独立持有,可将其声明为静态,在类外完成初始化:
class BatteryConfig { static float _defaultPackL1Undervoltage(); static FloatStorageNullableWithDefault packL1Undervoltage; }; FloatStorageNullableWithDefault BatteryConfig::packL1Undervoltage( "PackL1UndervoltageKey", BatteryConfig::_defaultPackL1Undervoltage );
错误原因说明
编译错误的核心是:在类成员的就地初始化语句中,编译器对_defaultPackL1Undervoltage的解析出现歧义,误将其识别为类型名而非函数名。通过上述方案,要么推迟初始化到构造函数阶段(让编译器能正确识别函数),要么显式转换类型消除歧义,即可解决「expected type specifier」错误。
内容的提问来源于stack exchange,提问作者Stéphane de Luca
相关产品推荐
相关产品推荐

