[英]Template function overloading in C++
我有以下定義。
using namespace std;
template <typename T>
void foo(const T &s) {
cout << 1;
}
template <typename T>
void foo(const T *s) {
cout << 2;
}
int main(int argc, const char * argv[]) {
char str[] = "ss";
char *s = str;
foo(s);
return 0;
}
然后輸出
1
根據我的理解,兩個版本都必須經過const轉換。 然后void foo(const T *s)
更專業,應該被調用。 但是編譯器選擇了void foo(const T& s)
。 解釋是什么?
有人指出編譯器選擇的模板參數
void f(char * const&)
void f(const char *);
在這里,請注意編譯器需要一個指向char, char*
的指針作為第一個函數,它是一個const引用。 可能會出乎意料,如果您發現對於您的情況它更喜歡第一個模板,但對於以下兩個模板, 它會更喜歡第二個模板
template <typename T>
void foo(const T& s) {
cout << 1;
}
template <typename T>
void foo(T &s) {
cout << 2;
}
所以,當然,它有時會看到const。 為什么不在你的情況下呢? 因為如果另一個函數也有引用,它只會查看const
作為引用。
在你的情況下,從char*
到const char*
它是一個指針轉換,但從lvalue
到const lvalue
,它實際上不是轉換。 通過const引用添加const將被重載決策忽略,除非兩個函數都具有上述情況中的引用參數。
原因是因為s是非const指針,所以int * const&實際上是比int const *更好的匹配,因為它不必將const添加到指針類型。
如果s是const限定的,那么它將與T const *版本完全匹配。
我已經移動了const
而沒有改變代碼的語義,所以當const
的位置稍后“改變”時你不會感到驚訝。
template <typename T>
void foo(T const &s) {
cout << 1;
}
template <typename T>
void foo(T const *s) {
cout << 2;
}
char *x = "x";
foo(x);
重載1必須將T
推導為char*
因此s
的類型將是char * const &
(引用指向非const char
const指針)。 這樣的引用可以綁定到參數類型( char *
;指向非const char
指針)而不進行任何轉換。
重載2必須將T
推導為char
因此s
的類型將是char const *
(指向const char
指針)。 這會導致從參數類型( char *
;指向非const char
指針)到參數類型( char const *
;指向const char
指針)的限定轉換。
過載1中的原理的更多說明性示例如下:
int n = 42;
int const &i = n;
將const引用綁定到非const實體不涉及轉換,因為它是添加限定條件的引用,它不是為了將它與引用類型匹配而添加到實體的限定條件。
兩個版本都必須經過const轉換。
第一個不需要轉換。 對於模板參數const T&
with template argument char *
, T
將推導為char*
,然后函數參數的類型將為char* const &
,因此它是完美匹配。 函數參數將被綁定為引用const( T
- > const T&
,即char*
到char* const&
),const qualified不是轉換。
對於第二個,模板參數const T*
與模板參數char *
, T
將推導為char
,然后函數參數的類型將是const char*
,並且需要限定轉換以將char*
轉換為const char*
。
從你的評論
這兩個例程都為
s
添加了低級const。
第一個是向s
添加const
,但第二個不是。 它將const
添加到s
指向的內容,而不是s
本身。 這是不同的。
原因是因為當參數是一個指針時,你必須傳入一個指針..像這樣:
// Example program
#include <iostream>
#include <string>
using std::cout;
using std::endl;
void foo(int *a)
{
cout << *a << endl;
}
int main()
{
int a = 5;
foo(&a);
}
但是如果你的參數是一個參考,你可以傳遞參數,如下所示:
// Example program
#include <iostream>
#include <string>
using std::cout;
using std::endl;
void foo(int &a)
{
cout << a << endl;
}
int main()
{
int a = 5;
foo(a);
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.