Insert a transformed integer_sequence into a variadic template argument?

Posted by coderforlife on Stack Overflow See other posts from Stack Overflow or by coderforlife
Published on 2014-06-08T20:16:14Z Indexed on 2014/06/08 21:24 UTC
Read the original article Hit count: 182

Filed under:
|
|

How do you insert a transformed integer_sequence (or similar since I am targeting C++11) into a variadic template argument?

For example I have a class that represents a set of bit-wise flags (shown below). It is made using a nested-class because you cannot have two variadic template arguments for the same class. It would be used like typedef Flags<unsigned char, FLAG_A, FLAG_B, FLAG_C>::WithValues<0x01, 0x02, 0x04> MyFlags. Typically, they will be used with the values that are powers of two (although not always, in some cases certain combinations would be made, for example one could imagine a set of flags like Read=0x1, Write=0x2, and ReadWrite=0x3=0x1|0x2). I would like to provide a way to do typedef Flags<unsigned char, FLAG_A, FLAG_B, FLAG_C>::WithDefaultValues MyFlags.

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

I have tried the following without success (placed inside the Flags class, outside the WithValues class):

private:
    struct _F {
        // dummy class which can be given to a flag-name template
        template <_B _V> inline constexpr
        explicit _F(std::integral_constant<_B, _V>) { } };

        // we count the flags, but only in a dummy way
        static constexpr unsigned _count = sizeof...(_Fs<_B, _F, 1>); 

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

    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;

Of course, I would be willing to have any other alternatives to the whole situation (supporting both flag names and values in the same template set, etc).

I have included a "working" example at ideone: http://ideone.com/NYtUrg - by "working" I mean compiles fine without using default values but fails with default values (there is a #define to switch between them).

Thanks!

© Stack Overflow or respective owner

Related posts about c++

Related posts about c++11