您的示例中没有模板扣除。Derived<int*> d(p);
专门将模板参数设置T
为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*>
需要一个指向 int 的 const 指针,因为T
is int*
。这可能看起来令人困惑,但您可以认为const
它具有比*
类型声明更高的优先级。因此,const int *
在const
应用于int
然后*
应用于整个事物中,创建指向 const intp
的指针,而 for中,const 适用于,这实际上是指向int的const 指针。const T
T
int*
const T argD
argD
使用相同的想法,您的所有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
If T
is const char*
(pointer to a 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
is char* const
(const pointer to a char) 那么所有的const T
重载都是多余的,因为const T
等价于T
whenT
已经是 const。
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 (+))