簡體   English   中英

C++ 枚舉類 std::size_t 隱式轉換

[英]C++ enum class std::size_t implicit conversion

我通過創建一個枚舉類定義了一個元組及其索引:

/** parameter { key ; value1 ; value1 ; } */
using Parameter = std::tuple<unsigned, unsigned, unsigned>;
enum class ParameterKey : std::size_t {
    KEY = 0,
    VALUE1 = 1,
    VALUE2 = 2
};

現在我想從這個元組中得到一個值:

const auto& key = std::get<ParameterKey::KEY>(*parameterPointer);

我認為從intstd::size_t的隱式轉換是由: std::size_t語法確保的:

enum class ParameterKey : std::size_t {
    ....
}

但我收到了這個錯誤

error: no matching function for call to ‘get<KEY>(std::tuple<unsigned int, unsigned int, unsigned int>&)’

這工作正常,但它太啰嗦了:

const auto& key = std::get<static_cast<unsigned>(ParameterKey::KEY)>(*parameterPointer);

這里沒有隱式轉換。 枚舉

盡管可以使用 static_cast 來獲取枚舉器的數值,但沒有從作用域枚舉器的值到整數類型的隱式轉換。

所以,你必須使用static_cast


有一些基於static_cast解決方法。 例如,可以使用std::underlying_type

template<typename T>
constexpr auto get_idx(T value)
{
    return static_cast<std::underlying_type_t<T>>(value);
}

然后:

const auto& key = std::get<get_idx(ParameterKey::KEY)>(*parameterPointer);

enum class的全部目的是不能隱式轉換為int ,因此沒有隱式轉換。

您可以創建自己的get版本:

template <ParameterKey key, typename Tuple>
decltype(auto) get(Tuple &&tuple) {
    return std::get<static_cast<std::underlying_type_t<ParameterKey>>(key)>(tuple);
}

然后:

const auto& key = get<ParameterKey::KEY>(*parameterPointer);

您可以通過創建接受此特定枚舉作為參數的數組/向量的特殊化來使轉換隱式:

template <typename ElementType, typename EnumType>
class enumerated_array: array<ElementType, static_cast<size_t>(EnumType::size_)>
{
    using ParentType = array<ElementType, static_cast<size_t>(EnumType::size_)>;
public:
    ElementType& operator[](EnumType enumerator)
    {
        return ParentType::operator[](static_cast<size_t>(enumerator));
    }
    const ElementType& operator[](EnumType enumerator) const
    {
        return ParentType::operator[](static_cast<size_t>(enumerator));
    }
};

// --------------------------------
// and that's how you use it:

enum class PixelColor: size_t { Red, Green, Blue, size_ };
enumerated_array<uint8_t, PixelColor> pixel;
// Can't use any other enum class as an index
pixel[PixelColor::Green] = 255;

此外,雖然這不是這個問題的主題,但這種方法與枚舉迭代器的協同作用非常好:

template <typename T>
class EnumRangeType
{
public:
    class Iterator
    {
    public:
        Iterator(size_t value):
            value_(value)
        { }

        T operator*() const
        {
            return static_cast<T>(value_);
        }

        void operator++()
        {
            ++value_;
        }

        bool operator!=(Iterator another) const
        {
            return value_ != another.value_;
        }

    private:
        size_t value_;
    };

    static Iterator begin()
    {
        return Iterator(0);
    }

    static Iterator end()
    {
        return Iterator(static_cast<size_t>(T::size_));
    }
};
template <typename T> constexpr EnumRangeType<T> enum_range;

// --------------------------------
// and that's how you use it:

void make_monochrome(enumerated_array<uint8_t, PixelColor>& pixel)
{
    unsigned int total_brightness = 0;
    for (auto color: enum_range<PixelColor>)
        total_brightness += pixel[color];

    uint8_t average_brightness = total_brightness/3;
    for (auto color: enum_range<PixelColor>)
        pixel[color] = average_brightness;
}    

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM