【问题标题】:Trouble with syntax for template-template-templates模板模板模板的语法问题
【发布时间】:2015-01-09 05:26:14
【问题描述】:

我正在写一个元函数MultipartitionWithUnaryPredicates,在表单中使用

MultipartitionWithUnaryPredicates<Pack<Args...>, UnaryPredicates...>::type

这样一个类型的模板包将由一元谓词包UnaryPredicates... 进行多分区,分区按一元谓词列出的顺序排列。如果您不确定我的意思,只需查看下面代码中的 main()(它可以正常工作):

#include <iostream>
#include <type_traits>
#include <typeInfo>

template <template <typename> class, typename, typename, typename> struct Helper;  

template <template <typename> class UnaryPredicate, template <typename...> class P, typename... Types1, typename... Types2>
struct Helper<UnaryPredicate, P<>, P<Types1...>, P<Types2...>> {
    using type = P<Types1..., Types2...>;
    using head = P<Types1...>;
    using tail = P<Types2...>;
};

template <template <typename> class UnaryPredicate, template <typename...> class P, typename First, typename... Rest, typename... Types1, typename... Types2>
struct Helper<UnaryPredicate, P<First, Rest...>, P<Types1...>, P<Types2...>> : std::conditional<UnaryPredicate<First>::value,
        Helper<UnaryPredicate, P<Rest...>, P<Types1..., First>, P<Types2...>>,
        Helper<UnaryPredicate, P<Rest...>, P<Types1...>, P<Types2..., First>>
    >::type {};

template <typename, template <typename> class> struct PartitionWithUnaryPredicate;

template <template <typename> class UnaryPredicate, template <typename...> class P, typename... Ts>
struct PartitionWithUnaryPredicate<P<Ts...>, UnaryPredicate> : Helper<UnaryPredicate, P<Ts...>, P<>, P<>> {};

template <typename, template <typename> class...> struct MultipartitionWithUnaryPredicates;

template <typename Pack, template <typename> class UnaryPredicate>
struct MultipartitionWithUnaryPredicates<Pack, UnaryPredicate> : PartitionWithUnaryPredicate<Pack, UnaryPredicate> {};

template <typename, typename> struct Join;

template <template <typename...> class P, typename... Types1, typename... Types2>
struct Join<P<Types1...>, P<Types2...>> {
    using type = P<Types1..., Types2...>;
};

//template <template <typename, template <typename> class> class Pack, typename... Ts>
//struct JoinSpecial : Join<typename Pack::head, typename MultipartitionWithUnaryPredicates<typename Pack::tail, Ts...>::type> {};

template <typename Pack, template <typename> class First, template <typename> class... Rest>
struct MultipartitionWithUnaryPredicates<Pack, First, Rest...> : Join<typename PartitionWithUnaryPredicate<Pack, First>::head, typename MultipartitionWithUnaryPredicates<typename PartitionWithUnaryPredicate<Pack, First>::tail, Rest...>::type> {};
// The above can be improved, since PartitionWithUnaryPredicate<Pack, First> is being computed twice.

// -----------------------------------------------------------------------------------------------------------------------------------------------
// Testing:

template <typename...> struct Pack {};

template <typename Last>
struct Pack<Last> {
    static void print() {std::cout << typeid(Last).name() << std::endl;}
};

template <typename First, typename ... Rest>
struct Pack<First, Rest...> {
    static void print() {std::cout << typeid(First).name() << ' ';  Pack<Rest...>::print();}
};

struct Thing {};
struct Blob { Blob(Blob&&){} };  // Copy constructor deleted.
struct Object {};
enum MyEnum {x, y, z};
enum HerEnum {xx, yy, zz};

int main() {
    MultipartitionWithUnaryPredicates<Pack<int, Thing, double, short, Blob, char, MyEnum, long, Object, float, HerEnum>,
        std::is_integral>::type b;
    b.print();  // int short char long Thing double Blob MyEnum Object float HerEnum

    MultipartitionWithUnaryPredicates<Pack<int, Thing, double, short, Blob, char, MyEnum, long, Object, float, HerEnum>,
        std::is_integral, std::is_enum>::type c;
    c.print();  // int short char long MyEnum HerEnum Thing double Blob Object float

    MultipartitionWithUnaryPredicates<Pack<int, Thing, double, short, Blob, char, MyEnum, long, Object, float, HerEnum>,
        std::is_integral, std::is_enum, std::is_arithmetic>::type d;
    d.print();  // int short char long MyEnum HerEnum double float Thing Blob Object

    MultipartitionWithUnaryPredicates<Pack<int, Thing, double, short, Blob, char, MyEnum, long, Object, float, HerEnum>,
        std::is_integral, std::is_enum, std::is_arithmetic, std::is_member_pointer, std::is_copy_constructible>::type e;
    e.print();  // int short char long MyEnum HerEnum double float Thing Object Blob
}

问题是试图优化上面的代码。

PartitionWithUnaryPredicate<Pack, First>

被计算了两次,我试图定义JoinSpecial,它只会使用一次。但我的语法不正确。

template <template <typename, template <typename> class> class Pack, typename... Ts>
struct JoinSpecial : Join<typename Pack::head, typename MultipartitionWithUnaryPredicates<typename Pack::tail, Ts...>::type> {};

不编译。模板类型PartitionWithUnaryPredicatetemplate &lt;typename, template &lt;typename&gt; class&gt; class 类型不是吗?

更新: 感谢 Angew 的提示,我现在得到了正确的语法:

template <template <typename, template <typename> class> class P, typename Pack, template <typename> class Pred, template <typename> class... Ts>
struct JoinSpecial : Join<typename P<Pack, Pred>::head, typename MultipartitionWithUnaryPredicates<typename P<Pack, Pred>::tail, Ts...>::type> {};

template <typename Pack, template <typename> class First, template <typename> class... Rest>
struct MultipartitionWithUnaryPredicates<Pack, First, Rest...> : JoinSpecial<PartitionWithUnaryPredicate, Pack, First, Rest...> {};

现在一切正常——我第一次使用模板模板,我必须说它看起来很丑。

【问题讨论】:

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


    【解决方案1】:

    JoinSpecial 的定义中,Pack 是一个类模板。然后,在为Join 指定模板参数时,您有typename Pack::headtypename Pack::tail。但是Pack 是一个模板,而不是一个类——你需要为Pack 提供模板参数。

    【讨论】:

    • 好的,所以我需要的确切语法是template &lt;template &lt;typename, template &lt;typename&gt; class&gt; class P, typename Pack, template &lt;typename&gt; class Pred, template &lt;typename&gt; class... Ts&gt; struct JoinSpecial : Join&lt;typename P&lt;Pack, Pred&gt;::head, typename MultipartitionWithUnaryPredicates&lt;typename P&lt;Pack, Pred&gt;::tail, Ts...&gt;::type&gt; {}; 唷!模板-模板-模板。
    猜你喜欢
    • 2012-11-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多