如果我们考虑函数模板重载,则C ++中的标准行为是首先选择“最专门的”重载(从基本模板中选择)。 下一步是查看所选重载是否明确专用。如果是,将选择匹配的显式专业化。
您能否指出定义第二步的标准中的位置(上一段中突出显示的部分)?
谢谢。
答案 0 :(得分:1)
从工作草案(N4713):
17.6.6.2功能模板的部分排序[临时功能]
1.如果功能模板过载,则使用功能模板专业化可能会模棱两可,因为模板参数推导可能会将功能模板专业化与多个功能模板声明相关联。重载函数模板声明的部分排序用于 以下上下文来选择功能模板专业化所指的功能模板:
(1.1)—在重载解析期间调用函数模板专门化功能;
(1.2)—使用功能模板专门化的地址时;
(1.3)—选择作为功能模板特化的放置运算符delete来匹配new的放置运算符;
(1.4)—当朋友函数声明,显式实例化或显式专门化是指函数模板专门化时。
也:
2 部分排序通过转换来选择两个功能模板中的哪个比另一个更专业 依次转换每个模板(请参阅下一段),然后使用函数执行模板参数推导 类型。 推论过程确定其中一个模板是否比另一个更专业。 如果是这样,则更专业的模板是部分订购过程选择的模板。如果两者都扣除 成功后,部分排序将选择约束更严格的模板,如17.4.4中的规则所述。
17.6.5.2类模板专业化的部分排序[temp.class.order]
1对于两个类模板的部分专业化,如果在以下重写为两个功能模板的情况下,第一个功能模板比第二个更专业,则第一个要比第二个更专业。 根据功能模板的订购规则(17.6.6.2): (1.1)—两个功能模板中的每一个都具有与相应的部分专业化相同的模板参数和关联的约束(17.4.2)。
(1.2)— 每个函数模板都有一个函数参数,其类型是类模板的特殊化,其中模板参数是函数模板中的对应模板参数 部分偏专业的simple-template-id的template-argument-list中的每个模板参数。
2 [示例:template<int I, int J, class T> class X { }; template<int I, int J> class X<I, J, int> { }; // #1 template<int I> class X<I, I, int> { }; // #2 template<int I0, int J0> void f(X<I0, J0, int>); // A template<int I0> void f(X<I0, I0, int>); // B template <auto v> class Y { }; template <auto* p> class Y<p> { }; // #3 template <auto** pp> class Y<pp> { }; // #4 template <auto* p0> void g(Y<p0>); // C template <auto** pp0> void g(Y<pp0>); // D
根据功能模板的排序规则,功能模板B比功能模板A更专业,功能模板D比功能模板C更专业。 因此,部分专业化#2比部分专业化#1更专业,部分专业化#4比部分专业化#3更专业。 —结束示例]
[示例:
template<typename T> concept C = requires (T t) { t.f(); }; template<typename T> concept D = C<T> && requires (T t) { t.f(); }; template<typename T> class S { }; template<C T> class S<T> { }; // #1 template<D T> class S<T> { }; // #2 template<C T> void f(S<T>); // A template<D T> void f(S<T>); // B
部分专业化#2比#1更专业,因为B比A更专业化。 —完示例]
答案 1 :(得分:1)
如果我对您的理解正确,那么也许您是从[temp.inst§4]引用此信息的:
除非已明确实例化功能模板专业化,或者已明确明确指定了功能模板,否则功能模板 当专门化是时,专门化被隐式实例化 在需要函数定义存在的上下文中引用 或是定义的存在影响了语义 程序[...]
通过否定,它表示显式专业化具有优先权。
答案 2 :(得分:0)
该标准没有正式定义什么是显式专业化。我可以找到的最相关的部分是[temp.expl.spec] / 1中的example:
[示例:
template<class T> class stream; template<> class stream<char> { /* ... */ }; template<class T> class Array { /* ... */ }; template<class T> void sort(Array<T>& v) { /* ... */ } template<> void sort<char*>(Array<char*>&);
鉴于这些声明,
stream<char>
将用作char
s流的定义;其他流将由从类模板实例化的类模板专业化处理。同样,sort<char*>
将用作类型Array<char*>
的参数的排序函数;其他Array
类型将根据模板生成的函数进行排序。 —示例]