explicit template specialization
显式%28%29模板专门化
允许为给定的一组模板参数自定义模板代码。
句法
template <> declaration | | |
---|
下列任何一项都可以完全专门化:
- 功能模板
- 类模板
- %28自C++14%29可变模板
- 成员函数类模板的
- 静态数据成员类模板的
- 成员类类模板的
- 成员枚举类模板的
- 成员类模板类或类模板的
- 成员函数模板类或类模板的
例如,
二次
#include <iostream>
template<typename T> // primary template
struct is_void : std::false_type
{
};
template<> // explicit specialization for T = void
struct is_void<void> : std::true_type
{
};
int main()
{
// for any type T other than void, the
// class is derived from false_type
std::cout << is_void<char>::value << '\n';
// but when T is void, the class is derived
// from true_type
std::cout << is_void<void>::value << '\n';
}
二次
详细
显式专门化可以在主模板定义为%28的任何作用域中声明,这可能与定义主模板的作用域不同,例如成员模板29%。显式专门化必须出现在非专门化模板声明之后。
二次
namespace N {
template<class T> class X { /*...*/ }; // primary template
template<> class X<int> { /*...*/ }; // specialization in same namespace
template<class T> class Y { /*...*/ }; // primary template
template<> class Y<double>; // forward declare specialization for double
}
template<>
class N::Y<double> { /*...*/ }; // OK: specialization in same namespace
二次
必须在第一次使用之前声明专门化,这将导致隐式实例化,在发生这种使用的每个翻译单元中:
二次
class String {};
template<class T> class Array { /*...*/ };
template<class T> void sort(Array<T>& v) { /*...*/ } // primary template
void f(Array<String>& v) {
sort(v // implicitly instantiates sort(Array<String>&),
} // using the primary template for sort()
template<> // ERROR: explicit specialization of sort(Array<String>)
void sort<String>(Array<String>& v // after implicit instantiation
二次
已声明但未定义的模板专门化可与任何其他专门化操作一样使用。不完全类型%28等。指针和对它的引用可以使用%29。
二次
template<class T> class X; // primary template
template<> class X<int>; // specialization (declared, not defined)
X<int>* p; // OK: pointer to incomplete type
X<int> x; // error: object of incomplete type
二次
函数模板的显式专门化
在对函数模板进行专门化时,如果模板参数推导可以通过函数参数提供它们:
二次
template<class T> class Array { /*...*/ };
template<class T> void sort(Array<T>& v // primary template
template<> void sort(Array<int>& // specialization for T = int
// no need to write
// template<> void sort<int>(Array<int>&
二次
具有与专门化相同的名称和参数列表的函数不是专门化%28(见功能[医]模板29%。
函数模板的显式专门化只有在使用内联说明符%28或定义为已删除的%29,如果主模板是内联的,则%27T不重要。
默认函数参数当类被隐式实例化时,不能在函数模板、成员函数模板和类模板的成员函数的显式专门化中指定。
显式专门化不能是朋友声明...
如果主模板具有%27T的异常规范noexcept(false)
,显式专门化必须具有兼容的异常规范。
专业成员
在类主体之外定义显式专门化类模板的成员时,语法template <>不使用,除非它%27是显式专门化成员类模板的成员,该成员模板是作为类模板专门化的,否则,语法将需要这样的定义。template<parameters>嵌套模板所需。
二次
template< typename T>
struct A {
struct B {}; // member class
template<class U> struct C { }; // member class template
};
template<> // specialization
struct A<int> {
void f(int // member function of a specialization
};
// template<> not used for a member of a specialization
void A<int>::f(int) { /* ... */ }
template<> // specialization of a member class
struct A<char>::B {
void f(
};
// template<> not used for a member of a specialized member class either
void A<char>::B::f() { /* ... */ }
template<> // specialization of a member class template
template<class U> struct A<char>::C {
void f(
};
// template<> is used when defining a member of an explicitly
// specialized member class template specialized as a class template
template<>
template<class U> void A<char>::C<U>::f() { /* ... */ }
二次
如果声明包含初始化程序,则模板的静态数据成员的显式专门化是定义;否则,则为声明。这些定义必须使用大括号进行默认初始化:
二次
template<> X Q<int>::x; // declaration of a static member
template<> X Q<int>::x ( // error: function declaration
template<> X Q<int>::x {}; // definition of a default-initialized static member
二次
类模板的成员或成员模板可以显式地专门化为类模板的给定隐式实例化,即使在类模板定义中定义了成员或成员模板。
二次
template<typename T>
struct A {
void f(T // member, declared in the primary template
void h(T) {} // member, defined in the primary template
template<class X1> void g1(T, X1 // member template
template<class X2> void g2(T, X2 // member template
};
// specialization of a member
template<> void A<int>::f(int
// member specialization OK even if defined in-class
template<> void A<int>::h(int) {}
// out of class member template definition
template<class T>
template<class X1> void A<T>::g1(T, X1) { }
// member template specialization
template<>
template<class X1> void A<int>::g1(int, X1
// member template specialization
template<>
template<> void A<int>::g2<char>(int, char // for X2 = char
// same, using template argument deduction (X1 = char)
template<>
template<> void A<int>::g1(int, char
二次
成员或成员模板可以嵌套在许多封装类模板中。在该成员的显式专门化中,有%27 s atemplate<>对于每个显式专门化的封闭类模板。
二次
template<class T1> class A {
template<class T2> class B {
void mf(
};
};
template<> template<> class A<int>::B<double>;
template<> template<> void A<char>::B<char>::mf(
二次
在这样的嵌套声明中,一些级别可能仍然是非专用%28,除非它可以在封装类为非专用%29的情况下专门化类成员模板。对于每个级别,声明都需要template<arguments>,因为这些专门化本身就是模板:
二次
template <class T1> class A {
template<class T2> class B {
template<class T3> void mf1(T3 // member template
void mf2( // non-template member
};
};
// specialization
template<> // for the specialized A
template<class X> // for the unspecialized B
class A<int>::B {
template <class T> void mf1(T
};
// specialization
template<> // for the specialized A
template<> // for the specialized B
template<class T> // for the unspecialized mf1
void A<int>::B<double>::mf1(T t) { }
// ERROR: B<double> is specialized and is a member template, so its enclosing A
// must be specialized also
template<class Y>
template<> void A<Y>::B<double>::mf2() { }
二次
缺陷报告
以下行为更改缺陷报告追溯应用于先前发布的C++标准。
DR | Applied to | Behavior as published | Correct behavior |
---|---|---|---|
CWG 727 | C++14 | full specializations not allowed in class scope, even though partial are | full specialization allowed in any scope |
另见
- 模板
- 类模板
- 功能模板
- 部分专业化
© cppreference.com
在CreativeCommonsAttribution下授权-ShareAlike未移植许可v3.0。