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