William
William

Reputation: 69

Can I use type traits to deduce the type of an enum from an enum value in c++?

In the example below I have created some fluent methods templated on enum values that test if a value contains a specific flag.

#include <type_traits>

// Scoped flags enum
enum class Flags {
    One = 1 << 0,
    Two = 1 << 1
};

// Template method for enum bitwise and operator
template< typename enum_type >
constexpr enum_type bitwise_and_operator(enum_type lhs, enum_type rhs) {
    typedef typename std::underlying_type<enum_type>::type fundamental_type;
    return static_cast<enum_type>(static_cast<fundamental_type>(lhs) & static_cast<fundamental_type>(rhs));
}

// Flags and operator
constexpr Flags operator&(Flags lhs, Flags rhs) {
    return bitwise_and_operator<Flags>(lhs, rhs);
}

// Template method for enum flag
template< typename enum_type, enum_type enum_value >
constexpr bool Flagged(enum_type type) {
    return (type & enum_value) == enum_value;
}

// Has flag one?
constexpr bool HasOne(Flags flags) {
    return Flagged<Flags, Flags::One>(flags);
};

// Has flag two?
constexpr bool HasTwo(Flags flags) {
    return Flagged<Flags, Flags::Two>(flags);
};


int main() {

    auto flag = Flags::One;

    auto True = HasOne(flag);
    auto False = HasTwo(flag);

    return 0;
}

Including both template parameters, Flags and Flags::One, is possibly more information than the compiler requires.

Is it possible to construct a template that could be called as:

constexpr bool HasOne(Flags flags) {
    return Flagged<Flags::One>(flags);
};

How would I construct a method that deduces the enum type from the value at compile time? Or is there another compile time solution to this problem?

Thanks in advance.

Upvotes: 0

Views: 282

Answers (2)

n. m. could be an AI
n. m. could be an AI

Reputation: 119847

As of now, only with a macro:

 #define FLAGGED(x,y) Flagged<decltype(x),x>(y)

There is a proposal in the works to fix this.

Upvotes: 0

Barry
Barry

Reputation: 302748

Any reason you want enum_value as a template parameter? You could simply pass it as another argument:

template <typename enum_type>
constexpr bool Flagged(enum_type src, enum_type flag) {
    return (src & flag) == flag;
}

// Has flag one?
constexpr bool HasOne(Flags flags) {
    return Flagged(flags, Flags::One);
};

Upvotes: 1

Related Questions