簡體   English   中英

C ++中的模板函數重載

[英]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*它是一個指針轉換,但從lvalueconst 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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM