Joh*_*itb 27
标准的"专业化"意味着将通用模板转换为更专业化的实体.例如,实例化非成员类模板会产生一个不再是模板的类.术语"特化"是双重的,可以指生成的特化(这是一种特殊化,可以从部分特化中实例化)和显式特化(这是你所提到的).
别名模板未实例化,并且没有它们的特化.他们无法实例化.相反,每当它们的名称后跟一个模板参数列表时,表示的类型是通过用别名类型替换名称和参数列表获得的类型,用参数列表中给出的参数替换所有模板参数引用.也就是说,别名模板本身不是别名的专用,而是作为别名,而不需要实例化任何东西.这种替换很早就完成了.考虑:
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 */ }
Run Code Online (Sandbox Code Playgroud)
替换是在ref<T>命名时完成的(这样的名称用于指代类或函数模板特化;因此规范描述了这些名称以"引用别名模板的特化").也就是说,f具有类型的参数T&,因此T可以推导出.此属性阻止别名模板的显式或部分特化.因为要选择正确的专业化ref,需要知道T.但要知道它,它需要ref<T>与推论的参数类型进行比较T.它在文章N1406,"C++的建议:Typedef模板",第2.2节中进行了总结
2.2主要选择:专业化与其他一切
在讨论了反射器和Evolution WG后,我们发现我们必须在两个相互排斥的模型之间进行选择:
typedef模板本身不是别名; 只有typedef模板的(可能是专用的)实例化才是别名.这个选择允许我们对typedef模板进行专门化.
typedef模板本身就是一个别名; 它不能专业化.这个选择将允许:
- 对typedef模板函数参数的推论(见2.4)
- 使用typedef模板表示的声明与不带typedef模板的声明相同(参见2.5)
- typedef模板以匹配模板模板参数(参见2.6)
应该注意的是,有利于选项1的引用文章没有使它成为C++ 0x.
编辑:因为你迫切希望有一个明确说明的规范引用.14.5p3是一个
由于别名声明无法声明模板ID,因此无法部分或显式地专门化别名模板.
如果您需要从某物到类型的逐点映射,这可以工作(在 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;
}
Run Code Online (Sandbox Code Playgroud)
我不确定我是否理解这个问题,但无论如何我试图模拟别名模板的专业化。
我认为这个想法是将别名模板限制为某些(模式匹配类型);我们曾经用这种代码做的事情:
template<class Vector> struct old_style;
template<class T> struct old_style<std::vector<T> >{
typedef typename std::vector<T>::value_type type;
};
Run Code Online (Sandbox Code Playgroud)
(这只是一个例子,还有其他方法可以提取value_type泛型的std::vector)。
现在到别名:
template<class Vector> using new_style = typename Vector::value_type;
Run Code Online (Sandbox Code Playgroud)
它做同样的工作,但这并不能取代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;
Run Code Online (Sandbox Code Playgroud)
不幸的是,它不能编译(理论上,由于其他答案和标准中所述的名义原因,实际上我想没有根本原因将其作为限制)。幸运的是,可以退回到老式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;
Run Code Online (Sandbox Code Playgroud)
可以使用 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;
Run Code Online (Sandbox Code Playgroud)
可以用作:
SPECIALIZED_ALIAS_TEMPLATE(new_style3, class T, std::vector<T>, typename std::vector<T>::value_type);
Run Code Online (Sandbox Code Playgroud)
如果需要任意数量的专业化(或代码中的非本地化),则必须使用更复杂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; \
};
Run Code Online (Sandbox Code Playgroud)
用法如下:
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);
Run Code Online (Sandbox Code Playgroud)
上面的所有代码都可以复制粘贴来测试:
#include<vector>
#include<map>
// ... paste code above //
int main(){
old_style<std::vector<double> >::type a; // is a double
// old_style<std::set<double> >::type a; // error (should work only for std::vector)
new_style2<std::vector<double> > b; // is double
// new_style2<std::set<double> > c; // error (should work only for std::vector)
new_style3<std::vector<double> > d; // is double
// new_style3<std::set<double> > d; // error (should work only for std::vector)
new_style4<std::vector<double> > e; // is double
new_style4<std::set<double> > f; // is double, this is another specialization
return 0;
}
Run Code Online (Sandbox Code Playgroud)
抱歉,如果这不是您要查找的内容。我相信它可以与可变参数模板一起使用,并且可以与额外的模板参数(在专业化中)一起使用,但没有对其进行测试。
改进是非常受欢迎的。
| 归档时间: |
|
| 查看次数: |
16775 次 |
| 最近记录: |