我對 C 中的模板引數推導有疑問。我不知道為什么下面的示例不起作用。樣品:
#include <iostream>
template<size_t n>
void PrintArray(const int arr[n]) {
for (int i = 0; i < n; i )
printf("%d\n", arr[i]);
}
int main() {
int arr[5] = {1, 2, 3, 3, 5};
PrintArray<>(arr);
return 0;
}
編譯器列印此錯誤:
main.cpp: In function 'int main()':
main.cpp:12:21: error: no matching function for call to 'PrintArray(int [5])'
PrintArray<>(arr);
^
main.cpp:4:6: note: candidate: template<unsigned int n> void PrintArray(const int*)
void PrintArray(const int arr[n]) {
^~~~~~~~~~
main.cpp:4:6: note: template argument deduction/substitution failed:
main.cpp:12:21: note: couldn't deduce template parameter 'n'
PrintArray<>(arr);
我發現如果我通過參考傳遞引數,代碼就可以作業了,所以函式簽名變成了這樣:
void PrintArray(const int (&arr)[n])
但為什么?當陣列按值傳遞時,您能否解釋一下為什么編譯器無法預測第一個示例中的陣列大小?
uj5u.com熱心網友回復:
這個函式宣告
void PrintArray(const int arr[n]) {
相當于
void PrintArray(const int *arr) {
由于編譯器將具有陣列型別的引數調整為指向陣列元素型別的指標。
來自 C 14 標準(8.3.5 函式)
5 一個名稱可以在一個范圍內用于多個不同的功能;這是函式多載(第 13 條)。函式的所有宣告在回傳型別和引數型別串列中都應完全一致。使用以下規則確定函式的型別。每個引數的型別(包括函式引數包)由其自己的 decl-specifier-seq 和 declarator 確定。在確定每個引數的型別后,任何型別為“T 的陣列”或“回傳 T 的函式”型別的引數分別調整為“指向 T 的指標”或“指向回傳 T 的函式的指標”。生成引數型別串列后,在形成函式型別時洗掉任何修改引數型別的頂級 cv 限定符。轉換后的引數型別的結果串列以及省略號或函式引數包的存在與否就是函式的引數型別串列。[ 注意:此轉換不影響引數的型別。例如, int( )(const int p, decltype(p) ) 和 int( )(int, const int ) 是相同的型別。— 尾注 ]
所以不可能推匯出模板引數n。
像這樣宣告函式
void PrintArray(const int ( &arr )[n]) {
或者您可以通過顯式指定模板引數來呼叫原始函式,例如
PrintArray<5>(arr);
轉載請註明出處,本文鏈接:https://www.uj5u.com/gongcheng/324806.html
