简体   繁体   English

模板参数推导和const限定

[英]Template argument deduction and const qualification

Could anyone explain why the code does not compile. 任何人都可以解释为什么代码不能编译。

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
}

The error message is that about no conversion from int* to const int* . 错误消息是没有从int*const int*转换。 As I see it T can be substitues by int* and in that case the constructor to Derived receives its argument as a const int* and invokes the base with const int* . 我看到它T可以是由substitues int*和在这种情况下,构造函数来Derived接收其参数为const int*和调用与碱const int* Why then is the constant qulaification getting lost. 那么为什么不断的诽谤会丢失。

I clearly do not understand how template argument deduction works. 我显然不明白模板参数推导是如何工作的。 I have not been able to find any lucid but rigorous and exhaustive description of how it works when const , * and & are in play. const*&发挥作用时,我无法找到任何清晰但严谨而详尽的描述。 That is, what will a get type deduced to in these various cases. 也就是说,什么都会a获取类型推断在这些各种情况。

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

when a is a

  • an object, 一个东西,
  • a pointer and 一个指针和
  • an array. 数组。

Because the constructor of Derived is Derived(const T argD) , so in your case it is Derived(int * const) . 因为Derived的构造函数是Derived(const T argD) ,所以在你的情况下它是Derived(int * const) This does not accept an const int* . 这不接受const int*

A "const (pointer to int)" is not a "(pointer to const int)" . “const(指向int的指针)”不是“(指向const int的指针)”

There is no template deduction in your example. 您的示例中没有模板推断。 Derived<int*> d(p); specifically sets the template parameter to T to int* ( pointer to int ). 具体将模板参数设置为T to int*指向int的指针 )。 Your derived constructor takes a const T parameter which is a const pointer to int in this case. 派生的构造函数采用const T参数,在这种情况下是一个指向intconst指针 I think your confusion is because const int* p; 我认为你的困惑是因为const int* p; does not declare a const pointer to int , but instead declares a pointer to const int which is not, and cannot be converted to, a const pointer to int (the former lets you modify the pointed to value while the latter does not). 不会声明一个指向intconst指针 ,而是声明一个指向const int指针,指针不是,也不能转换为指向intconst指针 (前者允许您修改指向的值,而后者则不会)。

Remember that C and C++ declarations are generally read from the variable name outwards, so for const int* p you start at p , go left and see * and then go farther left and see const int , so p is a pointer to a const int. 请记住,C和C ++声明通常从变量名称向外读取,因此对于const int* p ,从p开始,向左看并查看*然后再向左看并看到const int ,所以p是指向const int的指针。 Here is a good guide on deciphering C declarations and cdecl is also a very useful tool. 是解密C声明的好指南, cdecl也是一个非常有用的工具。

The problem with your example is p is a pointer to const int , but the constructor of Derived<int*> takes a const pointer to int since T is int* . 您的示例的问题是p指向const int指针 ,但Derived<int*>的构造函数将const指针指向int,因为Tint* This may seem confusing, but you can think of const as having a higher precedence than * in type declarations. 这可能看起来令人困惑,但您可以将const视为在类型声明中具有比*更高的优先级。 So in const int * the const applies to int and then * applies to the whole thing making p a pointer to const int whereas for const T , the const applies to T , which is actually int* so const T argD makes argD a const pointer to int . 所以在const int *const适用于int然后*适用于整个事情使p成为指向const int指针而对于const T ,const适用于T ,实际上是int*所以const T argD使argD成为const指针到int

Using this same idea all your Foo examples can be easily deciphered. 使用同样的想法,您可以轻松破译所有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

In general only Foo(T a) and Foo(const T a) cannot be overloaded because it doesn't matter to the caller whether the argument is copied into a constant variable or not. 通常只有Foo(T a)Foo(const T a)不能重载,因为调用者是否将参数复制到常量变量中并不重要。

More specifically, if T is char * (pointer to char) 更具体地说,如果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

If T is const char* (pointer to a const char) things are much the same 如果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

If T is char* const (const pointer to a char) then all the const T overloads are redundant because const T is equivalent to T when T is already const. 如果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