我想在C ++ 14中为模板映射做一个模板。先验,似乎以下代码可以解决这个问题
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
但是,使用 clang ++ v3.8 编译时,以下表达式将返回false。
template<template<class> class TemplateType>
struct NeedsTemplate;
std::is_same<
NeedsTemplate<ValueType>,
NeedsTemplate<Map<KeyType>::type>
>::value; // False
我明白为什么它是假的:it has already been answered here。基本上,该标准确保别名的模板实例化应该被识别为相同,但对模板本身没有任何说明。因此,使用 g ++ ,std::is_same
为真,而使用 clang ++ ,则为false。
我的问题是:如何使用g ++和clang ++实现模板映射,以满足std::is_same
要求?我愿意使用宏作为最后的手段...
答案 0 :(得分:1)
一般来说,你所要求的等同于功能比较,它等同于暂停问题,即不可计算。然而...
如果您只想对某些特定的预定义模板执行此操作,则可以将它们专门用于标记类,然后可以在标记类上使用NeedsTemplate。也就是说,
namespace Reflect {
struct Reflect {};
}
template<class T>
struct KeyType {};
namespace Reflect {
struct KeyType {};
}
template<>
struct KeyType<Reflect::Reflect> {
using type = Reflect::KeyType;
};
...然后使用KeyType<Reflect::Reflect>
,这是一种类型,而不是KeyType
,这是一个模板。请注意,您仍可以在界面上使用KeyType
(模板);你只需要反思std::is_same<>
。另请注意,这需要您为每种类型编写反射 - 虽然这对于宏来说是微不足道的。此外,您不能将Reflect::Reflect
用作键类型。 (你可以通过特征以另一种方式做到这一点,但是你会专注于特征的命名空间,这对于多个文件来说有点棘手。)
#define REFLECT_TEMPLATE(TEMPL) \
namespace Reflect { \
struct TEMPL {}; \
}; \
template<> \
struct TEMPL<Reflect::Reflect> { \
using type = Reflect::KeyType; \
};
如果我是你,我还会在反映的类型中添加const char* name() const
...
答案 1 :(得分:1)
不要将模板用作元编程原语。使用类型。类似,避免使用值。
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>;
您永远不会使用原始template
,只需使用ztemplate
s。
template<class T>
struct KeyType {};
using zKeyType=ztemplate<KeyType>;
C ++元编程可以更好地处理类型。如果你想要对你的类型进行限制(比如它必须是ztemplate
),请写SFINAE或伪造概念来强制执行它。
作为奖励,ztemplate
是定义模板的值。这让你开启了hana风格的元编程。
这意味着您必须规范地包装模板代码,并去除直接模板和值参数(分别替换为ztemplate和整型常量)。但你最终会得到更强大的元编程。
而不是X<Blah>
做apply<zX, Blah>
。实际上,apply
成为您直接使用的唯一模板。
注意apply<zapply, zX, Blah>
和apply<zapply, zapply, zX, Blah>
等与apply<zX, Blah>
相同。