[英]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
參數,在這種情況下是一個指向int的const指針 。 我認為你的困惑是因為const int* p;
不會聲明一個指向int的const指針 ,而是聲明一個指向const int的指針,該指針不是,也不能轉換為指向int的const指針 (前者允許您修改指向的值,而后者則不會)。
請記住,C和C ++聲明通常從變量名稱向外讀取,因此對於const int* p
,從p
開始,向左看並查看*
然后再向左看並看到const int
,所以p
是指向const int的指針。 這是解密C聲明的好指南, cdecl也是一個非常有用的工具。
您的示例的問題是p
是指向const int的指針 ,但Derived<int*>
的構造函數將const指針指向int,因為T
是int*
。 這可能看起來令人困惑,但您可以將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)
不能重載,因為調用者是否將參數復制到常量變量中並不重要。
更具體地說,如果T
是char *
(指向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
如果T
是const 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
如果T
是char* 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.