#include <iostream>
#include <type_traits>

//#define DONT_SUPPORT_DEFAULTS

template<class _B, template <class,class,_B> class... _Fs>
class Flags
{
public:
    template<_B... _Vs>
    class WithValues : public _Fs<_B, Flags<_B,_Fs...>::WithValues<_Vs...>, _Vs>...
    {
    public:
        typedef _B base_type;
        template <base_type _V>
	    inline constexpr explicit WithValues(std::integral_constant<base_type, _V>) : x(_V) { } // done in a strange way to allow the more natural constructor be non-constexpr
        inline explicit WithValues(base_type b) : x(b) { } // non-constexpr so I can add an exception to the body

        // ... (implementation details unnecessary)

    private: base_type x;
    };
private:
    struct _F { template <_B _V> inline constexpr explicit _F(std::integral_constant<_B, _V>) { } }; // dummy class which can be given to a flag-name template
    static constexpr unsigned _count = sizeof...(_Fs<_B, _F, 1>); // we count the flags, but only in a dummy way

    static inline constexpr _B pow2(unsigned exp, _B base = 2, _B result = 1) { return exp < 1 ? result : pow2(exp/2, base*base, (exp % 2) ? result*base : result); }

#ifndef DONT_SUPPORT_DEFAULTS
    template <_B... _Is>  struct indices          { using next = indices<_Is..., sizeof...(_Is)>; using WithPow2Values = WithValues<pow2(_Is)...>; };
    template <unsigned N> struct build_indices    { using type = typename build_indices<N-1>::type::next; };
    template <>           struct build_indices<0> { using type = indices<>; };

    //// Another attempt
    //template <            _B... _Is> struct indices { using WithPow2Values = WithValues<pow2(_Is)...>; };
    //template <unsigned N, _B... _Is> struct build_indices            : build_indices<N-1, N-1, _Is...> { };
    //template <            _B... _Is> struct build_indices<0, _Is...> : indices<_Is...>               { };

public:
    using WithDefaultValues = typename build_indices<_count>::type::WithPow2Values;
#endif
};

template <class _B, class _F, _B _V> struct FLAG_A { static constexpr const _F A = _F(std::integral_constant<_B,_V>()); };
template <class _B, class _F, _B _V> struct FLAG_B { static constexpr const _F B = _F(std::integral_constant<_B,_V>()); };
template <class _B, class _F, _B _V> struct FLAG_C { static constexpr const _F C = _F(std::integral_constant<_B,_V>()); };

typedef Flags<unsigned char, FLAG_A, FLAG_B, FLAG_C>::WithValues<1, 2, 4> MyFlags;
#ifndef DONT_SUPPORT_DEFAULTS
typedef Flags<unsigned char, FLAG_A, FLAG_B, FLAG_C>::WithDefaultValues MyFlags2;
#endif

int main()
{
    std::cout << "Compiled and ran!" << std::endl;
	return 0;
}