C++ 函数模板特化和重载
C++ function template specialization and overloading
考虑这段代码:
template <class T>
void f(T p) { //(1)
cout << "Second" << endl;
}
template <>
void f(int *p) { //(2)
cout << "Third" << endl;
}
template <class T>
void f(T* p) { //(3)
cout << "First" << endl;
}
如int *p; f(p);
这样的调用会输出First
。
如果改变声明的顺序,像这样:
template <class T>
void f(T* p) { //(3)
cout << "First" << endl;
}
template <class T>
void f(T p) { //(1)
cout << "Second" << endl;
}
template <>
void f(int *p) { //(2)
cout << "Third" << endl;
}
同样的调用(int *p; f(p);
)会输出Third
。
我了解了函数模板重载解析发生的方式:首先,解析仅考虑非模板函数和底层基础模板。选择 "most specialized" 之后,如果它是一个模板函数并且它对推导的(或明确指定的)参数具有特化,则调用该特化。
现在我的问题是:如何确定函数是哪个底层基础模板的特化?在我的示例中,哪个函数模板重载( (1) 或 (3) )是 (2) 特化?
我的猜测是,当声明一个专业化时,已经声明的模板被考虑,并从那些模板中选择最多 "specialized"(其参数是此专业化的 "closest")。这个对吗?另外,你能告诉我这是在标准中指定的地方吗?
它打印 "First" 因为声明的顺序会影响您实际专门化的模板。
您的示例有两个函数模板,它们重载了相同的名称。在第一种情况下,您专门化了 void f(T p)
,因为它是目前为止看到的唯一模板。
在第二种情况下,void f(T* p)
是特化的。所以是的,你的猜测是正确的。具体细节在 [temp.deduct.decl/1]:
In a declaration whose declarator-id refers to a specialization of a
function template, template argument deduction is performed to
identify the specialization to which the declaration refers.
Specifically, this is done for explicit instantiations, explicit
specializations, and certain friend declarations. [...]
这包括函数模板的部分排序。但是,部分排序仅适用于在您引入专业化时可用的函数模板声明。
并且标准在 [temp.expl.spec/7] 处发出警告:
The placement of explicit specialization declarations for function templates, [...] , can affect whether a program is well-formed
according to the relative positioning of the explicit specialization
declarations and their points of instantiation in the translation unit
as specified above and below. When writing a specialization, be
careful about its location; or to make it compile will be such a trial
as to kindle its self-immolation.
考虑这段代码:
template <class T>
void f(T p) { //(1)
cout << "Second" << endl;
}
template <>
void f(int *p) { //(2)
cout << "Third" << endl;
}
template <class T>
void f(T* p) { //(3)
cout << "First" << endl;
}
如int *p; f(p);
这样的调用会输出First
。
如果改变声明的顺序,像这样:
template <class T>
void f(T* p) { //(3)
cout << "First" << endl;
}
template <class T>
void f(T p) { //(1)
cout << "Second" << endl;
}
template <>
void f(int *p) { //(2)
cout << "Third" << endl;
}
同样的调用(int *p; f(p);
)会输出Third
。
我了解了函数模板重载解析发生的方式:首先,解析仅考虑非模板函数和底层基础模板。选择 "most specialized" 之后,如果它是一个模板函数并且它对推导的(或明确指定的)参数具有特化,则调用该特化。
现在我的问题是:如何确定函数是哪个底层基础模板的特化?在我的示例中,哪个函数模板重载( (1) 或 (3) )是 (2) 特化?
我的猜测是,当声明一个专业化时,已经声明的模板被考虑,并从那些模板中选择最多 "specialized"(其参数是此专业化的 "closest")。这个对吗?另外,你能告诉我这是在标准中指定的地方吗?
它打印 "First" 因为声明的顺序会影响您实际专门化的模板。
您的示例有两个函数模板,它们重载了相同的名称。在第一种情况下,您专门化了 void f(T p)
,因为它是目前为止看到的唯一模板。
在第二种情况下,void f(T* p)
是特化的。所以是的,你的猜测是正确的。具体细节在 [temp.deduct.decl/1]:
In a declaration whose declarator-id refers to a specialization of a function template, template argument deduction is performed to identify the specialization to which the declaration refers. Specifically, this is done for explicit instantiations, explicit specializations, and certain friend declarations. [...]
这包括函数模板的部分排序。但是,部分排序仅适用于在您引入专业化时可用的函数模板声明。
并且标准在 [temp.expl.spec/7] 处发出警告:
The placement of explicit specialization declarations for function templates, [...] , can affect whether a program is well-formed according to the relative positioning of the explicit specialization declarations and their points of instantiation in the translation unit as specified above and below. When writing a specialization, be careful about its location; or to make it compile will be such a trial as to kindle its self-immolation.