【问题标题】:Insert a transformed integer_sequence into a variadic template argument?将转换后的 integer_sequence 插入可变参数模板参数?
【发布时间】:2014-06-08 20:16:14
【问题描述】:

如何将转换后的 integer_sequence(或类似的,因为我的目标是 C++11)插入可变参数模板参数?

例如,我有一个代表一组位标志的类(如下所示)。它是使用嵌套类制作的,因为同一个类不能有两个可变参数模板参数。它将像typedef Flags<unsigned char, FLAG_A, FLAG_B, FLAG_C>::WithValues<0x01, 0x02, 0x04> MyFlags 一样使用。通常,它们将与 2 的幂的值一起使用(尽管并非总是如此,在某些情况下会进行某些组合,例如可以想象一组标志,如 Read=0x1、Write=0x2 和 ReadWrite=0x3 =0x1|0x2)。我想提供一种方法来做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>...
    {
        // ...
    };
};

我尝试了以下但没有成功(放置在 Flags 类中,在 WithValues 类之外):

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;

当然,我愿意为整个情况提供任何其他替代方案(支持同一模板集中的标志名称和值等)。

我在 ideone 中包含了一个“工作”示例:http://ideone.com/NYtUrg - “工作”是指在不使用默认值的情况下编译良好,但使用默认值失败(有一个 #define 在它们之间切换)。

谢谢!

【问题讨论】:

  • 不要使用以下划线开头的标识符,然后是大写字母。这些是为实现(编译器和标准库)保留的。
  • 谢谢。您是否还暗示下划线 - 小写字母好吗?我使用下划线来避免标志名称与标志类的“内部”使用名称发生冲突的问题。
  • @coderforlife 至于下划线,只需将它们向后放置以避免违反标准规则,例如B_而不是_B。这很容易:P ...
  • 没有阅读整篇文章。只需评论:It is made using a nested-class because you cannot have two variadic template arguments for the same class。实际上你可以使用元组:template &lt;class... Args1, class... Args2&gt; class X&lt;std::tuple&lt;Args1...&gt;, std::tuple&lt;Args2...&gt;。同样,没有阅读问题,对此感到抱歉,但这也许可以帮助您简化设计。
  • 这是一个有趣的想法,但是它在这里不起作用,因为一个可变参数模板不是类/类型名包而是一个整体包(因此解包一个整数序列)。我想可以制作一个类似元组的类来支持它......

标签: c++ templates c++11 variadic-templates


【解决方案1】:

所以我自己想通了,我想我发布得太早了。

我能够通过上面build_indicesindices 模板类中的虚拟模板参数解决给定代码生成的错误。参数必须是类型名,因为它们目前具有可变整数类型。

(注意:这里仍然使用不正确的 _F 名称 - 我已更正我的个人代码以不使用这些保留名称 - 感谢提示)

这是一个可行的解决方案,它会根据 Flags 可变参数模板的大小,用 2 的幂(1、2、4、8、16,...)填充 WithValues&lt;...&gt; 模板。

private:
// dummy class which can be given to a flag-name template
struct _F
{
    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 <class dummy, _B... _Is>  struct indices
{
    using next = indices<dummy, _Is..., sizeof...(_Is)>;
    using WithPow2Values = WithValues<pow2(_Is)...>;
};
template <class dummy, unsigned N> struct build_indices
{
    using type = typename build_indices<dummy, N-1>::type::next;
};
template <class dummy> struct build_indices<dummy, 0>
{
    using type = indices<dummy>;
};

public:
using WithDefaultValues =
        typename build_indices<void, _count>::type::WithPow2Values;

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-08-07
    • 1970-01-01
    • 2016-12-01
    • 2014-04-30
    • 2011-07-11
    • 1970-01-01
    • 2020-04-21
    相关资源
    最近更新 更多