1

マイクロコントローラー プロジェクトに次の C++11 コードがあります。

template<std::uint32_t... I>
struct mask_or;

template<>
struct mask_or<> {
    static constexpr std::uint32_t value = 0;
};

template<std::uint32_t first, std::uint32_t... rest>
struct mask_or<first, rest...> {
    static constexpr std::uint32_t value = first | mask_or<rest...>::value;
};

これは問題なく動作し、可変量の uint32_t をテンプレート引数として渡すことができます。次に、コンパイラはそれらすべてを OR し、各呼び出しを定数値に置き換えます。マイクロコントローラにとっては、レジスタに割り当てる前に OR 演算を実行する必要がないため、これは理想的です。

場合によっては、以下のような列挙型クラスを値として使用したい:

enum class gpiopin : std::uint32_t {
    p0 = GPIO_IDR_IDR_0, // 0x00000001
    ...
    p14 = GPIO_IDR_IDR_14, // 0x00004000
    p15 = GPIO_IDR_IDR_15 // 0x00008000
};

これらの列挙型クラスが複数あるため、上記の mask_or コードで列挙型クラスの値を使用する一般的な方法を探しています。要約すると、私はこれを行うことができるようにしたい:

SFR = mask_or<gpiopin::p1, gpiopin::p14>::value;

理想的には、mask_or<...>::value を constexpr にして、コード サイズを小さくし、速度を高速に保ちたいと考えています。

これは可能だと思いますが、うまくいかないようです。誰でも私を助けることができますか?

4

1 に答える 1

1

次のようなものを使用できます。

template<typename E, E... I>
struct mask_or;

template<typename E>
struct mask_or<E> {
    static constexpr E value = E(0);
};

template<typename E, E first, E... rest>
struct mask_or<E, first, rest...> {
    using UT = typename std::underlying_type<E>::type;
    static constexpr E value = E(UT(first) | UT(mask_or<E, rest...>::value));
};

ただし、最初のパラメーターとしてタイプを追加する必要があるため、これはまだ最適ではありません。

mask_or<gpiopin, gpiopin::p0, gpiopin::p14>::value

実際の例


単純にオーバーロードする方がはるかに簡単ですoperator|:

template<typename> struct is_bitmask : std::false_type {};

template<typename E>
constexpr
typename std::enable_if<is_bitmask<E>::value, E>::type
operator|( const E lhs, const E rhs )
{
    using UT = typename std::underlying_type<E>::type;
    return E(UT(lhs) | UT(rhs));
}

オペレーターのタイプを登録します

template<> struct is_bitmask<gpiopin> : std::true_type {};

これで、使用できます

gpiopin::p0 | gpiopin::p14

実際の例

于 2015-07-10T13:54:27.803 に答える