C++ 入门第 5 版。函数模板重载
C++ primer 5th ed. function template overloading
在C++ Primer一书中,有一个关于函数模板重载的例子:
// print any type we don't otherwise handle
template <typename T> string debug_rep(const T &t)
{
cout << "debug_rep(T const&)\n";
ostringstream ret; // see § 8.3 (p. 321)
ret << t; // uses T's output operator to print a representation of t
return ret.str(); // return a copy of the string to which ret is bound
}
// print pointers as their pointer value, followed by the object to which the pointer points
// NB: this function will not work properly with char*; see § 16.3 (p. 698)
template <typename T> string debug_rep(T *p)
{
std::cout << "debug_rep(T*)\n";
ostringstream ret;
ret << "pointer: " << p << '\n'; // print the pointer's own value
if (p)
ret << " " << debug_rep(*p); // print the value to which p points
else
ret << " null pointer"; // or indicate that the p is null
return ret.str(); // return a copy of the string to which ret is bound
}
If we call debug_rep with a pointer:
cout << debug_rep(&s) << endl;
both functions generate viable instantiations:
debug_rep(const string* &)
, which is the instantiation of the first version of debug_rep with T
bound to string*
debug_rep(string*)
, which is the instantiation of the second version of debug_rep
with T
bound to string*
The instantiation of the second version of debug_rep
is an exact match for this call.
The instantiation of the first version requires a conversion of the plain pointer to a pointer to const
. Normal function matching says we should prefer the second template, and indeed that is the one that is run.
但是,如果我将指向字符串的指针声明为 const
,尽管没有转换,但始终会选择第二个版本:
string const s("hi"); // const
cout << debug_rep(&s) << '\n';
所以我认为这是书中的一个错误,我认为因为版本采用指针是首选,因为我们传递的指针是 const
或不是(T
将被推断为 std::string const*
或 std::string*
).
你怎么看?
书错了
在第一个例子中,生成的实例化不是debug_rep(const string* &)
,而是debug_rep(string* const&)
。也就是说,const
限定指针,而不是指向的东西。 (如果本书使用正确的 const,这会更明显;也就是说,template <typename T> string debug_rep(T const& t)
用于第一个函数模板。)
确实,T
和 T const&
与函数模板重载具有同等优先级;在它们形成超载集的地方,它将是模棱两可的。选择 T*
而不是 T const&
的原因是它 更专业 ;简单地说,任意 T*
可以传递给采用 T const&
的函数,而任意 T const&
不能传递给采用 T*
.
的函数
在C++ Primer一书中,有一个关于函数模板重载的例子:
// print any type we don't otherwise handle template <typename T> string debug_rep(const T &t) { cout << "debug_rep(T const&)\n"; ostringstream ret; // see § 8.3 (p. 321) ret << t; // uses T's output operator to print a representation of t return ret.str(); // return a copy of the string to which ret is bound } // print pointers as their pointer value, followed by the object to which the pointer points // NB: this function will not work properly with char*; see § 16.3 (p. 698) template <typename T> string debug_rep(T *p) { std::cout << "debug_rep(T*)\n"; ostringstream ret; ret << "pointer: " << p << '\n'; // print the pointer's own value if (p) ret << " " << debug_rep(*p); // print the value to which p points else ret << " null pointer"; // or indicate that the p is null return ret.str(); // return a copy of the string to which ret is bound }
If we call debug_rep with a pointer:
cout << debug_rep(&s) << endl;
both functions generate viable instantiations:
debug_rep(const string* &)
, which is the instantiation of the first version of debug_rep withT
bound tostring*
debug_rep(string*)
, which is the instantiation of the second version ofdebug_rep
withT
bound tostring*
The instantiation of the second version of
debug_rep
is an exact match for this call.The instantiation of the first version requires a conversion of the plain pointer to a pointer to
const
. Normal function matching says we should prefer the second template, and indeed that is the one that is run.
但是,如果我将指向字符串的指针声明为 const
,尽管没有转换,但始终会选择第二个版本:
string const s("hi"); // const
cout << debug_rep(&s) << '\n';
所以我认为这是书中的一个错误,我认为因为版本采用指针是首选,因为我们传递的指针是 const
或不是(T
将被推断为 std::string const*
或 std::string*
).
你怎么看?
书错了
在第一个例子中,生成的实例化不是debug_rep(const string* &)
,而是debug_rep(string* const&)
。也就是说,const
限定指针,而不是指向的东西。 (如果本书使用正确的 const,这会更明显;也就是说,template <typename T> string debug_rep(T const& t)
用于第一个函数模板。)
确实,T
和 T const&
与函数模板重载具有同等优先级;在它们形成超载集的地方,它将是模棱两可的。选择 T*
而不是 T const&
的原因是它 更专业 ;简单地说,任意 T*
可以传递给采用 T const&
的函数,而任意 T const&
不能传递给采用 T*
.