成员函数的缩写参数,期望引入类型(枚举类) [英] Abbreviate argument to member function expecting introduced type (enum class)

查看:95
本文介绍了成员函数的缩写参数,期望引入类型(枚举类)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

TL; DR 成员函数的enum类类型参数是否有较短的语法( field_inst.write(decltype(field_inst):: Type :: cpr1_4096) ; )中的代码?

TL;DR Is there a Shorter syntax for the enum class type argument to a member function (field_inst.write(decltype(field_inst)::Type::cpr1_4096);) in the following code?

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 以来是否有所改进,这将使库更容易使用(更令人愉快的语法)。

However I want to know if there has been improvements since 2016 (date of question) / C++11 which would make the library easier to use (more pleasant syntax).

推荐答案

免责声明



此答案中提出的解决方案旨在满足最初的需求:编写简短但富有表现力的客户端代码。在这样做时,我将竭尽全力。对我而言,建议的行为是使用声音并使用声明,例如:

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);
    // ...
}



过度杀伤解决方案



您可以基于用户定义的文字设计一个(非常过度设计的)解决方案。

Overkill solution

You can devise a (very overengineered) solution based on user-defined literals.

// 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...>{};
}

}

然后,乐趣开始了。声明一个这样的特征类及其助手别名:

Then, the fun begins. Declare a trait class like this, along with its helper alias:

// Inside namespace Hal::Aeat_8800_Q24
template <typename T> struct setting_enum;
template <typename T>
using setting_enum_t = typename setting_enum<T>::type;

然后,为每个枚举专门化它:

Then, specialize it for each of your enums:

// (Still) Inside namespace Hal::Aeat_8800_Q24
using namespace literals;

template <>
struct SettingEnum<decltype("Cpr_Setting1"_as_iseq)> {
    using type = Cpr_Setting1;
};

最后,让我们定义最后一个文字运算符

Finally let's define a last literal operator

// 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...> >;
}

现在,您的客户代码只需要这样做:

Now your client code just needs to do this:

using namespace Hal::Aeat_8800_Q24::settings_literals;
// ...
field_inst.write(decltype("Cpr_Setting1"_s)::cpr1_4096);

那还很长……有什么方法可以做得更好?是的,的确是。。。而不是使用上述特征,而是使用变量模板。

That's still quite long... Is there a way to do better? Yes indeed... Instead of using the trait above let's use a variable template instead.

// 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

变量模板需要针对每个枚举的每个值进行专门化(这很繁琐!我会向任何可以进行预处理技巧的人扔掉帽子,以避免手工编写所有样板代码)

The variable template needs to be specialized for each value of each enum (that's tedious! I'll throw my hat to anyone that can do preprocessor tricks to avoid writing all that boilerplate code by hand)

让我们向写成员函数添加重载:

Let's add an overload to the write member function:

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_);
    }
};

最后,客户端代码将如下所示:

In the end, the client code will look like this:

field_int.write("cpr1_4096"_as_iseq);

现在我们在说!在 Coliru

Now we're talking! Demo on Coliru.

这篇关于成员函数的缩写参数,期望引入类型(枚举类)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆