2016-01-22 21 views
3

我想寫一個函數,它會在控制檯上打印數據。該函數將被模板化,因爲它應該接受不同類型的數據。C++ 11 for循環在一個模板函數

的代碼如下所示:

template<typename DataType> 
void PrintData(DataType *X) 
{ 
    for (DataType Data : X) 
    { 
     cout << Data << "\t"; 
    } 
    cout << endl; 
} 

int main() 
{ 

    int nArray[7] = { 7, 5, 4, 3, 9, 8, 6 }; 
    double dArray[5] = { 4.3, 2.5, -0.9, 100.2, 3.0 }; 

    PrintData(nArray); 
    PrintData(dArray); 

    system("pause"); 
    return EXIT_SUCCESS; 
} 

我得到一個錯誤可變數據是在模板函數PrintData未申報

error C2065: 'Data' : undeclared identifier 
error C3312: no callable 'begin' function found for type 'double *'  
error C3312: no callable 'begin' function found for type 'int *'  
error C3312: no callable 'end' function found for type 'double *'  
error C3312: no callable 'end' function found for type 'int *' 

任何幫助,將不勝感激。 謝謝

+0

我敢肯定你的不僅僅是你所提到的一個得到了更多的錯誤。 –

+4

'DataType *'不是數組或容器類型,循環範圍無法處理它。更重要的是,所寫的'PrintData'不知道'X'指向的元素的數量。如果你想要走這條路,可以把它設爲'template void PrintData(DataType(&X)[N]){...}'。 [Demo](http://rextester.com/XYYXJF94394) –

+0

謝謝你的回答。我有其他疑問。 main()函數中的以下代碼是如何工作的: for(auto Data:nArray) cout << Data << endl; – Barry

回答

4

假設您已包含iostream頭文件和using namespace std;指令。那麼你的問題是:

  1. 你不應該使用DataType *。您的代碼使X指針與數組不同。改爲使用DataType const&DataType&&
  2. 您必須包含iterator頭文件,該文件提供了C風格陣列的beginend函數。

以下代碼適用於我。

#include <iostream> 
#include <iterator> 
using namespace std; 

template<typename DataType> 
void PrintData(DataType const& X) 
{ 
    for (auto Data : X) 
    { 
     cout << Data << "\t"; 
    } 
    cout << endl; 
} 

int main() 
{ 

    int nArray[7] = { 7, 5, 4, 3, 9, 8, 6 }; 
    double dArray[5] = { 4.3, 2.5, -0.9, 100.2, 3.0 }; 

    PrintData(nArray); 
    PrintData(dArray); 

    return EXIT_SUCCESS; 
} 

正如評論由Igor Tandetnik,你可以,如果你想引用數組的大小使用template<struct DataType, size_t N>

更新:

  1. 隨着template<struct DataType>DataType *XDataType推導爲intdouble,並X是一個指針,它不是一個容器。
  2. 隨着template<struct DataType, size_t N>DataType (&X)[N]和,DataType推導爲intdouble,並X是能夠與基於範圍循環中使用的陣列。
  3. 隨着template<struct DataType>DataType&& XDataType const& XDataType推導作爲int[7]double[5],並X是一個數組爲好。
+0

謝謝你的解釋。但我仍然不明白DataTpye(&X)[N]簽名... – Barry

+0

讓'Type'是某種類型,然後'Type&X'聲明一個參考權利?在這種情況下,'Type'只是被'DataType [N]'取代。回想一下你如何聲明一個指向數組的指針。但是請注意,你不能這麼做:'typedef DataType(&Type)[N]'因爲在許多情況下C風格的數組將被轉換爲指針。如果你想知道爲什麼,請進行搜索。 – cqdjyy01234

2

問題是你傳遞的數組名稱(例如,nArray),它基本上只是一個指向第一個元素的指針。但是,新款for循環期望您可以撥打beginend - 一個範圍。

以下更改通過使用vector而不是數組來工作。請注意,除此之外幾乎沒有什麼區別,並且通常在當代C++中使用C風格數組的原因很少。

#include <iostream>                                               
#include <vector> 

using namespace std; 

template<typename DataType> 
void PrintData(const DataType &X) 
{ 
    for (const auto &Data : X) 
    { 
     cout << Data << "\t"; 
    } 
    cout << endl; 
} 

int main() 
{ 

    vector<int> nArray = { 7, 5, 4, 3, 9, 8, 6 }; 
    vector<double> dArray = { 4.3, 2.5, -0.9, 100.2, 3.0 }; 

    PrintData(nArray); 
    PrintData(dArray); 

    system("pause"); 
    return EXIT_SUCCESS; 
+0

我感謝你的回答,下次我會使用像載體一樣的容器。 – Barry

+0

不客氣。 –

1

你有一些問題:

1)數據類型必須是一個容器。所以,儘量使用:

std::vector<int> nArray = { 7, 5, 4, 3, 9, 8, 6 }; 
std::vector<double> dArray = { 4.3, 2.5, -0.9, 100.2, 3.0 }; 

2)你不打算改變容器。這是更好地const引用傳遞容器:

template<typename DataType> 
void PrintData(const DataType & X); 

3)改變這樣的循環:

for (const auto & value : X) { 
    std::cout << value << "\t"; 
} 

代碼示例:

#include <iostream> 
#include <vector> 

template<typename DataType> 
void PrintData(const DataType & X) { 
    for (const auto & value : X) { 
     std::cout << value << "\t"; 
    } 
    std::cout << std::endl; 
} 

int main() { 
    std::vector<int> nArray = { 7, 5, 4, 3, 9, 8, 6 }; 
    std::vector<double> dArray = { 4.3, 2.5, -0.9, 100.2, 3.0 }; 
    PrintData(nArray); 
    PrintData(dArray); 
    return 0; 
} 
1

由於伊戈爾建議,如果你想使用DataType *那麼你需要做這樣的事情

#include <iostream> 
#include <iterator> 
using namespace std; 

template <typename DataType, size_t N> 
void PrintData(DataType (&X)[N]) 
{ 
    for (auto i : X) 
     cout << i << "\t"; 

    cout << endl; 
} 

int main() 
{  
    int nArray[7] = { 7, 5, 4, 3, 9, 8, 6 }; 
    double dArray[5] = { 4.3, 2.5, -0.9, 100.2, 3.0 }; 

    PrintData(nArray); 
    PrintData(dArray); 

    return EXIT_SUCCESS; 
} 

輸出

7 5 4 3 9 8 6 
4.3 2.5 -0.9 100.2 3 

說明:

如果看到void PrintData(int* nArray); & void PrintData(int (&nArray)[7]); 是相似的聲明,除了秒一個告訴其中陣列結束。

模板功能

template <typename DataType, size_t N> 
void PrintData(DataType (&X)[N]) 

被推斷爲

void PrintData(int (&nArray)[7]) 

你也可以寫

void PrintData(int (&nArray)[7]) 
{ 
    for (auto i : nArray) 
     cout << i << "\t"; 

    cout << endl; 
}