【问题标题】:Indices trick used for several components用于多个组件的索引技巧
【发布时间】:2015-07-06 15:00:36
【问题描述】:

考虑这个完全工作的代码:

#include <type_traits>

template <typename T, typename IndexPack> struct Make;

template <typename T, template <T...> class P, T... Indices>
struct Make<T, P<Indices...>> {
    using type = P<(Indices+1)..., (-3*Indices)..., (Indices-1)...>;
};

template <int...> class Pack;

int main() {
    static_assert (std::is_same<Make<int, Pack<1,2,3,4>>::type, 
        Pack<2,3,4,5, -3,-6,-9,-12, 0,1,2,3>>::value, "false");
}

我真正想要的输出是

Pack<2,-3,0, 3,-6,1, 4,-9,2, 5,-12,3>

而不是Pack&lt;2,3,4,5, -3,-6,-9,-12, 0,1,2,3&gt;。我第一次尝试

using type = P<(Indices+1, -3*Indices, Indices-1)...>;

但编译器只是将其理解为无用的逗号运算符。获得我想要的东西所需的语法是什么?如果没有这样的语法,那么最简洁的方法是什么,请记住使用Indices 3 次只是一个示例(我们可能希望使用它超过 3 次)。请不要告诉我我必须编写一个助手来提取各个包,然后“交错”所有元素。这种噩梦般的方法不可能是最好的解决方案(而且这种解决方案也只有在我们确切知道要提取多少个单独的包时才有效)。

定义

template <typename T, template <T...> class P, T I>
struct Component {
    using type = P<I+1, -3*I, I-1>;
};

以某种方式帮助?对此进行包扩展?

【问题讨论】:

  • 我不确定编写一个函数来做某事是否如此噩梦——如果你试图在 runtime 做同样的事情,这正是你会做的事情.
  • @Hurkyl。实际上,这并不是那么噩梦,你是对的。但是下面哥伦布的解决方案要好得多。

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


【解决方案1】:

是的,您可以递归连接:

template <typename, typename, typename> struct Concat;

template <typename T, template <T...> class P, T... A, T... B>
struct Concat<T, P<A...>, P<B...>> {
    using type = P<A..., B...>;
};

template <typename T, typename IndexPack> struct Make;

template <typename T, template <T...> class P, T... I, T F >
struct Make<T, P<F, I...>> {
    using type = typename Concat<T,
                                 typename Make<T, P<F>>::type,
                                 typename Make<T, P<I...>>::type>::type;
};

template <typename T, template <T...> class P, T I>
struct Make<T, P<I>> {
    using type = P<I+1, -3*I, I-1>;
};

Demo

【讨论】:

  • @orlp 我知道那是什么感觉。
【解决方案2】:

这是受到 Columbo 解决方案的启发。它使用了我最初寻求的包扩展语法,即

using type = typename Merge<T, typename Component<T, P, Indices>::type...>::type;

因此,现在Make 是可重用的,首先使用Triple,然后使用Quadruple,因此可以同时扩展任意数量的Indices 用法。这里Component是传入Make的template-template-template参数:

#include <type_traits>

template <typename T, typename... Packs> struct Merge;

template <typename T, template <T...> class P1, template <T...> class P2, T... Is, T... Js>
struct Merge<T, P1<Is...>, P2<Js...>> {
    using type = P1<Is..., Js...>;
};

template <typename T, typename Pack1, typename Pack2, typename... Packs>
struct Merge<T, Pack1, Pack2, Packs...> {
    using type = typename Merge<T, Pack1, typename Merge<T, Pack2, Packs...>::type>::type;
};

template <typename T, template <T...> class P, T I>
struct Triple {
    using type = P<I+1, -3*I, I-1>;
};

template <typename T, template <T...> class P, T I>
struct Quadruple {
    using type = P<I+1, -3*I, I-1, I>;
};

template <typename T, typename IndexPack,
    template <typename U, template <U...> class P, U I> class Component> struct Make;

template <typename T, template <T...> class Z, T... Indices,
    template <typename U, template <U...> class P, U I> class Component>
struct Make<T, Z<Indices...>, Component> {
    using type = typename Merge<T, typename Component<T, Z, Indices>::type...>::type;
};

template <int...> class Pack;

int main() {
    static_assert (std::is_same<Make<int, Pack<1,2,3,4>, Triple>::type,
        Pack<2,-3,0, 3,-6,1, 4,-9,2, 5,-12,3>>::value, "false");

    static_assert (std::is_same<Make<int, Pack<1,2,3,4>, Quadruple>::type,
        Pack<2,-3,0,1, 3,-6,1,2, 4,-9,2,3, 5,-12,3,4>>::value, "false");
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-12-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-10-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多