簡體   English   中英

模板參數推導和const限定

[英]Template argument deduction and const qualification

任何人都可以解釋為什么代碼不能編譯。

template<class T, class DER>
struct Base {
  T a;
  Base(const T argB) : a(argB){}
};

template<class T>
struct Derived : Base<T, Derived<T> > {
  Derived(const T argD) : Base<T, Derived<T> >(argD){}
};

int main() {
  int val = 10;
  const int *p = &val;
  /* this was in the original question
  Derived<int*> d(p); // breaks, but compiles with Derived<const int*> d(p);
  */
  Derived d(p); // fails, but Derived<const int*> d(p); compiles
}

錯誤消息是沒有從int*const int*轉換。 我看到它T可以是由substitues int*和在這種情況下,構造函數來Derived接收其參數為const int*和調用與鹼const int* 那么為什么不斷的誹謗會丟失。

我顯然不明白模板參數推導是如何工作的。 const*&發揮作用時,我無法找到任何清晰但嚴謹而詳盡的描述。 也就是說,什么都會a獲取類型推斷在這些各種情況。

 Foo(T& a)
 Foo(T  a)
 Foo(T* a)
 Foo(const T a)
 Foo(const T*a)
 Foo(const t&a)

a

  • 一個東西,
  • 一個指針和
  • 數組。

因為Derived的構造函數是Derived(const T argD) ,所以在你的情況下它是Derived(int * const) 這不接受const int*

“const(指向int的指針)”不是“(指向const int的指針)”

您的示例中沒有模板推斷。 Derived<int*> d(p); 具體將模板參數設置為T to int*指向int的指針 )。 派生的構造函數采用const T參數,在這種情況下是一個指向intconst指針 我認為你的困惑是因為const int* p; 不會聲明一個指向intconst指針 ,而是聲明一個指向const int指針,指針不是,也不能轉換為指向intconst指針 (前者允許您修改指向的值,而后者則不會)。

請記住,C和C ++聲明通常從變量名稱向外讀取,因此對於const int* p ,從p開始,向左看並查看*然后再向左看並看到const int ,所以p是指向const int的指針。 是解密C聲明的好指南, cdecl也是一個非常有用的工具。

您的示例的問題是p指向const int指針 ,但Derived<int*>的構造函數將const指針指向int,因為Tint* 這可能看起來令人困惑,但您可以將const視為在類型聲明中具有比*更高的優先級。 所以在const int *const適用於int然后*適用於整個事情使p成為指向const int指針而對於const T ,const適用於T ,實際上是int*所以const T argD使argD成為const指針到int

使用同樣的想法,您可以輕松破譯所有Foo示例。

Foo(T& a)       // a is a reference to a value of type T
Foo(T  a)       // a is a value of type T
Foo(T* a)       // a is a pointer to a value of type T
Foo(const T a)  // a is a constant value of type T
Foo(const T* a) // a is a pointer to a constant value of type T
Foo(const T& a) // a is a reference to a constant value of type T

通常只有Foo(T a)Foo(const T a)不能重載,因為調用者是否將參數復制到常量變量中並不重要。

更具體地說,如果Tchar * (指向char的指針)

Foo(char *&a)       // a is a reference to a pointer to a char
Foo(char *a)        // a is a pointer to a char (*)
Foo(char **a)       // a is a pointer to a pointer to a char
Foo(char *const a)  // a is a constant pointer to a char (cannot overload with (*))
Foo(char *const *a) // a is a pointer to a constant pointer to a char
Foo(char *const &a) // a is a reference to a constant pointer to a char

如果Tconst char* (指向const char*指針),事情就大致相同了

Foo(const char *&a)       // a is a reference to a pointer to a const char
Foo(const char *a)       // a is a pointer to a const char (*)
Foo(const char **a)       // a is a pointer to a pointer to a const char
Foo(const char *const a)  // a is a constant pointer to a const char (cannot overload with (*))
Foo(const char *const *a) // a is a pointer to a constant pointer to a const char
Foo(char *const &a) // a is a reference to a constant pointer to a const char

如果Tchar* const (指向char的const指針),則所有const T重載都是冗余的,因為當T已經是const時, const T等於T

Foo(char *const &a) // a is a reference to a const pointer to a char (+)
Foo(char *const a)  // a is a const pointer to a char (*)
Foo(char *const *a) // a is a pointer to a const pointer to a char (^)
Foo(char *const a)  // a is a const pointer to a char (same as (*))
Foo(char *const *a) // a is a pointer to a const pointer to a char (same as (^))
Foo(char *const &a) // a is a reference to a const pointer to a char (same as (+))

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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