别名模板专业化

Lig*_*ica 30 c++ templates c++11

别名模板(14.5.7)可以明确专门化(14.7.3)吗?

我的标准fu失败了,我找不到要测试的编译器.

文本"当模板ID引用别名模板的特化时"意味着,但是然后该示例似乎引用了其他内容,暗示没有.

NB.我在n3242工作,一个在FDIS后面,其中这一部分的标题是"别名模板".大声笑.

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后,我们发现我们必须在两个相互排斥的模型之间进行选择:

  1. typedef模板本身不是别名; 只有typedef模板的(可能是专用的)实例化才是别名.这个选择允许我们对typedef模板进行专门化.

  2. typedef模板本身就是一个别名; 它不能专业化.这个选择将允许:

    • 对typedef模板函数参数的推论(见2.4)
    • 使用typedef模板表示的声明与不带typedef模板的声明相同(参见2.5)
    • typedef模板以匹配模板模板参数(参见2.6)

应该注意的是,有利于选项1的引用文章没有使它成为C++ 0x.


编辑:因为你迫切希望有一个明确说明的规范引用.14.5p3是一个

由于别名声明无法声明模板ID,因此无法部分或显式地专门化别名模板.

  • @alfc:仅当您想要专门化typedef时.我后来意识到这并不是那么糟糕 - 你可以拥有专门模板的模板别名.只有别名本身不能被专门化,这在实践中并不常见. (3认同)
  • 哇,这消除了我对模板别名的大部分预期用途。我期待着摆脱除了保存 typedef 之外没有任何用途的结构。 (2认同)

Ale*_*kov 9

如果您需要从某物到类型的逐点映射,这可以工作(在 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)


Lig*_*ica 7

Bjarne :

专业化工作(您可以为一组专业化设置别名,但不能专门化别名)

而且,虽然不是一个明确的规则,但是在14.7.3/1的以下列表中缺少"别名模板":

以下任何一种明确的专业化:

  • 功能模板
  • 类模板
  • 类模板的成员函数
  • 类模板的静态数据成员
  • 类模板的成员类
  • 类或类模板的成员类模板
  • 类或类模板的成员函数模板

可以宣布[...]

我认为这是您获得的最佳保证.


alf*_*lfC 5

我不确定我是否理解这个问题,但无论如何我试图模拟别名模板的专业化。

我认为这个想法是将别名模板限制为某些(模式匹配类型);我们曾经用这种代码做的事情:

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)

抱歉,如果这不是您要查找的内容。我相信它可以与可变参数模板一起使用,并且可以与额外的模板参数(在专业化中)一起使用,但没有对其进行测试。

改进是非常受欢迎的。