缩写对成员函数期望引入类型(ENUM类)的论点
Abbreviate argument to member function expecting introduced type (enum class)
tl; dr 在以下代码中,eNum类类型参数( field_inst.write(decltype(field_inst)::Type::cpr1_4096);
)是否有较短的语法?
namespace Hal {
// complex template definition `Bit_Field`
template<
class Tregister,
typename Tregister::Data Toffset,
typename Tregister::Data Tmask,
class Tfield_type,
class Tmutability_policy = typename Tregister::Mutability_Policy
>
struct Bit_Field : Tregister {
using Type = Tfield_type;
static Field read()
{ // ... reading ...
}
};
namespace Aeat_8800_Q24 {
enum class {cpr1_4096 = 0x5,
// ... more settings ...
};
} // namespace Aeat_8800_Q24
} // namespace HAl
int main(void) {
// this template is used multiple times, different template arguments
// on each instantiation (using / typedef not practical)
Hal::Bit_Field<reg<0x8FA>, 0x0, 0x7, Hal::Aeat_8800_Q24::Cpr_Setting1>
field_inst;
// QUESTION: How can I write that more pleasingly?
field_inst.write(decltype(field_inst)::Type::cpr1_4096);
field_inst.write(Hal::Aeat_8800_Q24::Cpr_Setting1::cpr1_4096);
}
免责声明:问题本身是重复的:在成员函数参数中使用嵌套枚举类时,如何防止类资格。
但是,我想知道自2016年以来(问题的日期)/c 11 以来是否有改进,这将使库更易于使用(更愉快的语法)。
免责声明
此答案中提出的解决方案打算回答原始需求:编写较短但表现力的客户代码。这样,我将竭尽所能。对我来说,建议的行为是使用声音using
声明的使用,例如:
int main() {
using Hal::Aeat_8800_Q24::Cpr_Setting1;
// Or if enums are alone and well encapsulated in their namespace:
//using namespace Hal::Aeat_8800_Q24;
Hal::Bit_Field<reg<0x8FA>, 0x0, 0x7, Cpr_Setting1>
field_int;
field_int.write(Cpr_Setting1::cpr1_4096);
// ...
}
过杀
您可以根据用户定义的文字设计(非常设计的)解决方案。
// This is just a little helper for later
namespace literals {
template <typename T, T... Cs>
constexpr auto operator ""_as_iseq() {
return std::integer_sequence<T, Cs...>{};
}
}
然后,乐趣开始了。声明这样的特质类,以及其助手别名:
// Inside namespace Hal::Aeat_8800_Q24
template <typename T> struct setting_enum;
template <typename T>
using setting_enum_t = typename setting_enum<T>::type;
然后,为您的每个枚举都专业:
// (Still) Inside namespace Hal::Aeat_8800_Q24
using namespace literals;
template <>
struct SettingEnum<decltype("Cpr_Setting1"_as_iseq)> {
using type = Cpr_Setting1;
};
终于定义最后一个字面的操作员
// Inside namespace Hal::Aeat_8800_Q24
namespace settings_literals {
template <typename T, T... Cs>
constexpr auto operator""_s()
-> setting_enum_t<
std::integer_sequence<T, Cs...> >;
}
现在,您的客户端代码只需要这样做:
using namespace Hal::Aeat_8800_Q24::settings_literals;
// ...
field_inst.write(decltype("Cpr_Setting1"_s)::cpr1_4096);
那还很长...有没有办法做得更好?是的,确实...而不是使用上面的特征,让我们使用变量模板。
// In namespace Hal
namespace enum_traits {
using namespace literals;
template <typename Enum, typename ValueIntSeq>
constexpr void *ENUM_VALUE = nullptr;
template <>
constexpr Aeat_8800_Q24::Cpr_Setting1 ENUM_VALUE<
Aeat_8800_Q24::Cpr_Setting1, decltype("cpr1_4096"_as_iseq)> =
CprSetting1::cpr1_4096;
// ...
} // ns enum_traits
需要专门针对每个枚举的每个值都专门化(这很繁琐!我会把帽子扔给任何可以做预处理器技巧的人,以避免手工编写所有样板代码)
让我们在写入成员函数中添加一个过载:
struct BitField : Tregister {
// ...
template <typename T, T... Cs>
void write(std::integer_sequence<T, Cs...> s) {
constexpr auto v_ = enum_traits::ENUM_VALUE<Type, decltype(s)>;
static_assert(
!std::is_pointer_v<decltype(v_)>,
"Invalid enum int sequence provided");
write(v_);
}
};
最后,客户端代码看起来像这样:
field_int.write("cpr1_4096"_as_iseq);
现在我们在谈论!演示 coliru 。
相关文章:
- 是否可以从int转换为enum类类型
- 在一个模板函数中,若输入的类型是enum类,我该如何使用std::underlying_type
- 如何理解c++中在命名空间内部定义的枚举类型enum
- 将枚举类型保存在位字段 [dcl.enum] [class.bit] 中
- 在使用C 中使用多个三元运算符时,BOOL和ENUM类型超载的功能没有区分
- 缩写对成员函数期望引入类型(ENUM类)的论点
- "enum class"是C++中的类类型吗?
- 为什么C/C++会自动将char/wchar_t/short/bool/enum类型转换为int
- c++ Visual Studio, 'vc_attributes::YesNoMaybe' : 'enum' 类型重定义错误
- 我可以在DLL边界使用“enum class”作为函数的参数类型吗
- C++函数,接受enum并返回要在模板中使用的typedef类类型
- QMetaEnum和强类型enum
- 将Enum转换为布尔类型
- 相当于enum类型的boost::program_options::bool_switch
- 通过ENUM查找返回元组值(不同类型)的模板函数
- 是否可以将int(enum)映射为类型
- 在 QT 中,错误:ISO C++禁止转发对'enum'类型的引用
- c++数组初始化器.使用enum类型
- 指定枚举基础类型时的"ISO C++ forbids forward references to 'enum' types"
- 专门化仅适用于带有enum非类型模板参数的c++模板函数