简体   繁体   English

模板到C ++ 14中的模板映射

[英]Template to template map in C++14

I want to do a template to template map in C++14. 我想在C ++ 14中为模板映射做一个模板。 A priori, it seems that the following code does the trick 先验,似乎以下代码可以解决问题

template<class T>
struct KeyType {};

template<class T>
struct ValueType {
    T x;
};

template<template<class> class K>
struct Map;

template<>
struct Map<KeyType> {
    template<class T>
    using type = ValueType<T>;
};

ValueType<int> test{42};
Map<KeyType>::type<int> testM{42}; // Same as above

However, the following expression, when compiled with clang++ v3.8 , returns false. 但是,使用clang ++ v3.8编译时,以下表达式返回false。

template<template<class> class TemplateType>
struct NeedsTemplate;

std::is_same<
    NeedsTemplate<ValueType>,
    NeedsTemplate<Map<KeyType>::type>
>::value; // False

I understand why it is false: it has already been answered here . 我理解为什么它是假的: 它已在这里得到解答 Basically, the standard assures that template instantiations of aliases should be recognize as the same, but says nothing about templates them-self. 基本上,该标准确保别名的模板实例化应该被识别为相同,但对模板本身没有任何说明。 Hence, with g++ , std::is_same is true, and with clang++ , it is false. 因此,使用g ++std::is_same为true,而使用clang ++ ,则为false。

My question is: how can I implement a template to template map that will satisfy the std::is_same requirement both with g++ and clang++? 我的问题是:如何使用g ++和clang ++实现模板映射,以满足std::is_same要求? I'm willing to use macro as a last resort... 我愿意用宏作为最后的手段......

What you're asking for, in general, is equivalent of functional comparison which is equivalent to the halting problem, ie, not computable. 一般来说,你所要求的等同于功能比较,它等同于停止问题,即不可计算。 However... 然而...

If you only want to do this for some specific, pre-defined templates, you can specialize them for a tag class and then you can use NeedsTemplate on the tag class. 如果您只想为某些特定的预定义模板执行此操作,则可以将它们专门用于标记类,然后可以在标记类上使用NeedsTemplate。 That is, 那是,

namespace Reflect {
    struct Reflect {};
}

template<class T>
struct KeyType {};

namespace Reflect {
    struct KeyType {};
}

template<>
struct KeyType<Reflect::Reflect> {
    using type = Reflect::KeyType;
};

... and then work with KeyType<Reflect::Reflect> , which is a type, instead of KeyType , which is a template. ...然后使用KeyType<Reflect::Reflect> ,这是一种类型,而不是KeyType ,它是一个模板。 Note that you might still take KeyType (template) on the interface; 请注意,您仍然可以在界面上使用KeyType (模板); you just call std::is_same<> on reflections. 你只需要在反射上调用std::is_same<> Also note, this requires you to write the reflection for each type - albeit that's trivial with macros. 另请注意,这需要您为每种类型编写反射 - 虽然这对于宏来说是微不足道的。 Also, you can't use Reflect::Reflect as a key type. 此外,您不能将Reflect::Reflect用作键类型。 (You could do this the other way, via traits, but then you're specializing in the traits' namespace, which is a bit tricky with multiple files.) (你可以通过特征以另一种方式做到这一点,但是你专注于特征的命名空间,这对于多个文件来说有点棘手。)

#define REFLECT_TEMPLATE(TEMPL) \
    namespace Reflect {                \
        struct TEMPL {};               \
    };                                 \
    template<>                         \
    struct TEMPL<Reflect::Reflect> {   \
        using type = Reflect::KeyType; \
    };

If I were you, I'd also add a const char* name() const to the reflected type... 如果我是你,我还会在反射类型中添加一个const char* name() const ...

Don't use templates as your metaprogramming primitives. 不要将模板用作元编程原语。 Use types. 使用类型。 Similar, avoid values. 类似,避免价值观。

template<template<class...>class Z>
struct ztemplate{
  template<class...Ts>
  using apply=Z<Ts...>;
};
template<class Z, class...Ts>
using apply=typename Z::template apply<Ts...>;
using zapply=ztemplate<apply>;

You never work with raw template s, just ztemplate s. 你永远不会使用原始template ,只需ztemplate s。

template<class T>
struct KeyType {};
using zKeyType=ztemplate<KeyType>;

C++ metaprogramming works much nicer with types. C ++元编程在类型上更好用。 If you want restrictions on your types (like it must be a ztemplate ) write SFINAE or psuedo-concepts to enforce it. 如果你想要对你的类型进行限制(比如它必须是一个ztemplate ),请编写SFINAE或ztemplate的概念来强制执行它。

As a bonus, a ztemplate is a value that defines a template. 作为奖励, ztemplate是定义模板的 Which opens you up to hana-style metaprogramming. 这让你开启了hana风格的元编程。

This does mean you have to canonically wrap your template code, and strip out direct template and value parameters (replacing with ztemplate and integral constant respectively). 这意味着您必须规范地包装模板代码,并去除直接模板和值参数(分别替换为ztemplate和整型常量)。 But you end up with much more powerful metaprogramming. 但是你最终会得到更强大的元编程。

Instead of X<Blah> do apply<zX, Blah> . 而不是X<Blah> apply<zX, Blah> In effect, apply becomes the only template you directly use. 实际上, apply是您直接使用的唯一模板。

Note apply<zapply, zX, Blah> and apply<zapply, zapply, zX, Blah> etc is the same as apply<zX, Blah> . 注意apply<zapply, zX, Blah>apply<zapply, zapply, zX, Blah>等与apply<zX, Blah>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM