别名模板(14.5.7)可以明确专门化(14.7.3)吗?
我的标准功能使我失望,我找不到要测试的编译器。
文本“当模板ID引用别名模板的特化时”暗示是,但是示例似乎引用了其他内容,暗示否
NB。我在n3242工作,一个在FDIS后面,其中本节的标题是“别名模板”。洛尔。子>
答案 0 :(得分:26)
“专业化”标准的含义是将通用模板转换为更专业的实体。例如,实例化非成员类模板会产生一个不再是模板的类。术语“专业化”是两个部分,可以指生成的特化(这是一个实例化的特化,可能来自部分特化)和一个显式特化(这是你所提到的)。
别名模板未实例化,并且没有专门化的模板。他们无法实例化。相反,每当它们的名称后跟一个模板参数列表时,表示的类型是通过用别名类型替换名称和参数列表获得的类型,用参数列表中给出的参数替换所有模板参数引用。也就是说,别名模板本身不是别名的专用,而是作为别名,而不需要实例化任何东西。这种替换很早就完成了。考虑:
template<typename T> using ref = T&;
template<typename T> void f(ref<T> x) { x = 10; }
int main() { int a; f(a); return a; /* 10 */ }
替换是在命名ref<T>
时完成的(这样的名称用于指代类或函数模板特化;因此规范描述了这样的名称以“引用别名模板的特化”) 。也就是说,f
的参数具有类型T&
,因此可以推导出T
。此属性阻止别名模板的显式或部分特化。因为要选择ref
的正确专长,需要知道T
。但要知道它,它需要将ref<T>
与参数类型进行比较以推导出T
。它在文章N1406, "Proposed addition to C++: Typedef Templates",第2.2节
2.2主要选择:专业化与其他一切
经过对反射器和Evolution WG的讨论后,我们发现我们必须在两种相互排斥的模型之间进行选择:
typedef模板本身不是别名;只有typedef模板的(可能是专用的)实例化才是别名。这个选择允许我们对typedef模板进行专门化。
- 醇>
typedef模板本身就是一个别名;它不能专业化。这个选择将允许:
- 对typedef模板函数参数的推论(见2.4)
- 使用typedef模板表示的声明与不声明声明相同 typedef templates(见2.5)
- typedef模板以匹配模板模板参数(参见2.6)
应该注意的是,所引用的论文(有利于选项1)没有使其成为C ++ 0x。
编辑:因为你非常想要一个明确说明的规范引用。 14.5p3就是
由于别名声明无法声明模板ID,因此无法部分或明确地专门化别名模板。
答案 1 :(得分:7)
Bjarne says:
专业化工作(您可以为一组专业化设置别名,但不能专门化别名)
而且,虽然不是一个明确的规则,但是在14.7.3 / 1的以下列表中缺少“别名模板”:
以下任何一项的明确专业化:
- 功能模板
- 课程模板
- 类模板的成员函数
- 类模板的静态数据成员
- 类模板的成员类
- 类或类模板的成员类模板
- 类或类模板的成员函数模板
可以声明[...]
我认为这是您获得的最佳保证。
答案 2 :(得分:4)
我不确定我是否理解这个问题,但无论如何我试图模拟别名模板的特化。
我认为这个想法是将别名模板限制为某些(模式匹配类型);我们以前用这种代码做的事情:
template<class Vector> struct old_style;
template<class T> struct old_style<std::vector<T> >{
typedef typename std::vector<T>::value_type type;
};
(这只是一个示例,还有其他方法可以提取通用value_type
的{{1}}。
现在到了别名:
std::vector
它执行相同的工作,但这不会取代template<class Vector> using new_style = typename Vector::value_type;
,因为它不是限制性的。第一次尝试使用完美的别名替换是这个假设的代码:
old_stype<...>::type
不幸的是它没有编译(理论上由于其他答案和标准中所述的名义原因,实际上我认为这没有根本原因成为限制)。幸运的是,人们可以采用旧式的//template<class Vector> using new_style2; // error already here
//template<class T> using new_style2<std::vector<T> > = typename Vector::value_type;
方式回归,只使用新的别名模板功能来转发工作,
struct::type
可以使用template<class Vector> struct new_style2_aux;
template<class T> struct new_style2_aux<std::vector<T> >{
typedef typename std::vector<T>::value_type type;
};
template<class Vector> using new_style2 = typename new_style2_aux<Vector>::type;
define
可以用作:
#define SPECIALIZED_ALIAS_TEMPLATE(NamE, Pattern_arG, PatterN_expR, DefinitioN) \
template<class> struct NamE ## _aux; \
template<Pattern_arG> struct NamE ## _aux<PatterN_expR>{ \
typedef DefinitioN type; \
}; \
template<class NamE ## _dummy> using NamE = typename NamE ## _aux< NamE ## _dummy >::type;
如果需要任意数量的特化(或代码中的非本地化),则必须在两个部分中使用更复杂的SPECIALIZED_ALIAS_TEMPLATE(new_style3, class T, std::vector<T>, typename std::vector<T>::value_type);
,一个用于声明,一个用于专门化(应该是):
define
使用如下:
#define DECLARE_ALIAS_TEMPLATE(NamE)\
template<class> struct NamE ## _aux;\
template<class NamE ## _dummy> using NamE = typename NamE ## _aux< NamE ## _dummy >::type;
#define SPECIALIZE_ALIAS_TEMPLATE(NamE, Pattern_arG, PatterN_expR, DefinitioN)\
template<Pattern_arG> struct NamE ## _aux<PatterN_expR>{ \
typedef DefinitioN type; \
};
上面的所有代码都可以复制并粘贴到测试中:
DECLARE_ALIAS_TEMPLATE(new_style4);
SPECIALIZE_ALIAS_TEMPLATE(new_style4, class T, std::vector<T>, typename std::vector<T>::value_type);
SPECIALIZE_ALIAS_TEMPLATE(new_style4, class T, std::set<T>, typename std::set<T>::value_type);
很抱歉,如果这不是您想要的。我相信它可以与变量模板一起使用,并使用额外的模板参数(在专业化中),但没有测试它。
非常欢迎改进。
答案 3 :(得分:3)
如果你需要从某些东西到类型的逐点映射,这适用于(在gcc 4.8.3中):
// int to type mapper
template<int BITS>
struct BitsToTypesMap
{
typedef void TYPE; // default
};
// pointwise mapping
template<>
struct BitsToTypesMap<32>{ typedef int TYPE; };
template<>
struct BitsToTypesMap<8>{ typedef char TYPE; };
template<>
struct BitsToTypesMap<16>{ typedef short TYPE; };
// cute wrapping
template<int BITS> using MyScalarType = typename BitsToTypesMap<BITS>::TYPE;
// TEST
template<int BITS>
MyScalarType<BITS>
Add ( MyScalarType<BITS> x, MyScalarType<BITS> y )
{
return x+y;
}
int
test()
{
MyScalarType<32> i=Add<32>(1,2);
MyScalarType<8 > b=Add<8 >(1,2);
MyScalarType<16> s=Add<16>(1,2);
return i+b+s;
}