template <typename T>
// 1:
void compare(T, T) {}
int main{
compare("123", "45");
}
// T is const char *
// 2:
void compare(T *, T *) {}
// T is const char
// 3:
void compare(const T *, const T *) {}
// T is char
// 4:
void compare(const T, const T) {}
// T is const char *
1:
我的问题是根据我完全理解的1,2,3模式
为什么T变成它的样子。而第4码中的T不是我假设的char *
。
2:
为什么第一个代码和第4个代码产生相同类型的T。
3:
我可以使用reference
中的const char *
作为compare
中的参数
答案 0 :(得分:2)
我的问题是根据1,2,3的模式,我可以完全理解为什么T变成它的样子。而第4码中的T不是我假定的char *。
因为您被误导了以识别错误的模式。这是为什么“前导const误导”的一个示例。模板与宏不同,const
在左侧的放置并不意味着它适用于char
。它适用于整个参数类型,并且由于参数将是指针(由于将文字作为参数给出),因此综合函数将如下所示:
void compare(char const* const, char const* const) {}
这就是为什么许多C ++程序员(包括我自己)都喜欢使用cv-qualifers不同位置的原因。您的选项3和4会这样写:
void compare(T const *, T const *) {}
// T is char
// 4:
void compare(T const, T const ) {}
// T is const char *
它更一致,因为const
始终适用于它左边的内容(如果有的话,否则会有一个异常,并且是一个令人困惑的异常)。而且,这也使人们清楚地知道了(无论如何,IMO)当推论结束后,什么将是常量。
答案 1 :(得分:1)
第4个代码中的T不是我假定的
char *
。
请注意,在第四代码中,const
直接在T
上限定。当推导出T
作为指针时,则const T
表示const
指针,而不是指向const
的指针。因此,将T
推导为const char*
,第四个compare
的自变量将为const char * const
。
让我们假设将T
推导出为char *
,那么const T
将是char * const
(即指向非const
的{{1}}指针const
),显然不是预期的参数类型。
我可以使用对
char
的引用作为const char *
中的参数
我不确定我是否正确理解了您的问题,是的,您可以编写类似compare
的内容以将其更改为通过引用,但是还要注意void compare(const T&, const T&)
compare("123", "45");
被推导为数组类型(在这种情况下,推论实际上将失败,因为T
和"123"
不是同一数组类型),不会发生数组到指针的衰减。这可能不是您所期望的。
答案 2 :(得分:1)
对compare
的调用获取字符串文字,其类型为const char *
;
1:我的问题是根据1,2,3的模式,我可以 完全理解为什么T变成它的样子。 第4个代码不是我假定的char *。
在const T
中,常量引用T,即const char*
。 const in
const char*
表示字符。 const的两种情况涉及不同的事物。使用const T x
,我们无法更改x,即指针x本身。使用const char* x
,我们可以更改指针,但不能更改x指向的字符。
2:为什么第一个代码和第4个代码导致相同类型的 T。
请参阅上面的答案。 const T
中的const对于调用者来说是多余的。调用者不在乎实现是否会更改其指针副本。只有实现才在乎。
3:我可以在compare中使用const char *的引用作为参数吗?
当然,只需编写const T&
或const char*const&
(从右到左读取:对指向字符常量的常量指针的引用)