重载时在定义之前声明函数模板
Declaring function templates before defining when overloading
C++ Primer 5th Edition 在第 16.3 章(讨论函数模板重载的一章)末尾有一段建议:
Declare every function in an overload set before you define any of the
functions. That way you don’t have to worry whether the compiler will
instantiate a call before it sees the function you intended to call.
这是否告诉我,在重载决策期间选择候选函数和可行函数时,编译器可能会实例化最终未选择的函数模板?我试着看看这是否真的会发生:
template<class> struct always_false : std::false_type {};
template <typename T> void test(T const &){
static_assert(always_false<T>::value, "If this fires, it is instantiated");
}
template <typename T> void test(T*) { }
int main(){
int *q = nullptr;
test(q); //test(T*) should be the best match
}
如果 test(T const &)
以任何形式实例化,此程序将抛出编译器错误,除非程序按预期正常编译。那么那个提示试图保护我免受什么样的编译事故?它什么时候会在看到我试图调用的函数之前实例化一个函数?
作者警告您:
template<class> struct always_false : std::false_type {};
template <typename T> void test(T const &){
static_assert(always_false<T>::value, "If this fires, it is instantiated");
}
int main(){
int *q = nullptr;
test(q); //test(T*) will not be matched.
}
template <typename T> void test(T*)
{
}
还有这些:
template<class> struct always_false : std::false_type {};
template <typename T> void test(T const &){
static_assert(always_false<T>::value, "If this fires, it is instantiated");
}
template <> void test<int>(int const &);
void test(int *);
int main(){
int *q = nullptr;
test(q); //test(int*) should be the best match
int a;
test(a); // test<int>(int const&) should be the best match
}
template <> void test<int>(int const &)
{
}
void test(int *)
{
}
如果您不提供
的声明
template <> void test<int>(int const &);
void test(int *);
在 main
之前,它们不会在 main
中匹配。
我见过很多 SO 问题,它们是
的一些变体
template<class T, class... Ts>
T sum(T t, Ts... ts) { return t + sum(ts...); }
// ^ |
// |--------------------------------
// only one visible in
// definition context
template<class T>
T sum(T t) { return t; }
int main() {
sum(1, 2); // doesn't compile
}
(return 类型并不完美,但你明白了。)
然后当它没有编译时人们会感到惊讶。
或者,更有趣,
template<class T> void f(T t) { f((int)t); }
void f(int) { /*...*/ }
int main() {
f(1L); // infinite recursion
}
C++ Primer 5th Edition 在第 16.3 章(讨论函数模板重载的一章)末尾有一段建议:
Declare every function in an overload set before you define any of the functions. That way you don’t have to worry whether the compiler will instantiate a call before it sees the function you intended to call.
这是否告诉我,在重载决策期间选择候选函数和可行函数时,编译器可能会实例化最终未选择的函数模板?我试着看看这是否真的会发生:
template<class> struct always_false : std::false_type {};
template <typename T> void test(T const &){
static_assert(always_false<T>::value, "If this fires, it is instantiated");
}
template <typename T> void test(T*) { }
int main(){
int *q = nullptr;
test(q); //test(T*) should be the best match
}
如果 test(T const &)
以任何形式实例化,此程序将抛出编译器错误,除非程序按预期正常编译。那么那个提示试图保护我免受什么样的编译事故?它什么时候会在看到我试图调用的函数之前实例化一个函数?
作者警告您:
template<class> struct always_false : std::false_type {};
template <typename T> void test(T const &){
static_assert(always_false<T>::value, "If this fires, it is instantiated");
}
int main(){
int *q = nullptr;
test(q); //test(T*) will not be matched.
}
template <typename T> void test(T*)
{
}
还有这些:
template<class> struct always_false : std::false_type {};
template <typename T> void test(T const &){
static_assert(always_false<T>::value, "If this fires, it is instantiated");
}
template <> void test<int>(int const &);
void test(int *);
int main(){
int *q = nullptr;
test(q); //test(int*) should be the best match
int a;
test(a); // test<int>(int const&) should be the best match
}
template <> void test<int>(int const &)
{
}
void test(int *)
{
}
如果您不提供
的声明template <> void test<int>(int const &);
void test(int *);
在 main
之前,它们不会在 main
中匹配。
我见过很多 SO 问题,它们是
的一些变体template<class T, class... Ts>
T sum(T t, Ts... ts) { return t + sum(ts...); }
// ^ |
// |--------------------------------
// only one visible in
// definition context
template<class T>
T sum(T t) { return t; }
int main() {
sum(1, 2); // doesn't compile
}
(return 类型并不完美,但你明白了。)
然后当它没有编译时人们会感到惊讶。
或者,更有趣,
template<class T> void f(T t) { f((int)t); }
void f(int) { /*...*/ }
int main() {
f(1L); // infinite recursion
}