I can't make a reverse call inside a template function,though the parameters passed to it seems no problem. First is the header file:
#ifndef TestTemplate_TestTemplate_h
#define TestTemplate_TestTemplate_h
template<int size>
void printArray(int (*iarr)[size]);
#include "TestTemplate.cpp"
#endif
second is the .cpp file:
#include <iostream>
using std::cout;
using std::endl;
template<int size>
void printArray(int (*iarr)[size]){
if(size == 1){
return;
}
else{
const int s = size - 1;
cout << size << endl;
int arr[s][s] = {};
printArray<s>(arr);
}
}
Last is the main file:
#include <iostream>
#include "TestTemplate.h"
int main(int argc, const char * argv[])
{
const int size = 4;
int iarr[size][size]= {{1, 2, 3, 4}, {1, 2, 3, 4}, {1, 2, 3, 4}, {1, 2, 3, 4}};
printArray<size>(iarr);
}
now I got a compilation error saying that
no matching function for call to 'printArray'
in the source file. Maybe there's some grammars in template programming I don't know here.Wish somebody can point it to me.Thanks very much.
You cannot terminate template recursion (which is generated entirely at compile time) by using run-time constructs like if. The compiler always has to instantiate both branches of your if inside printArray, even if it "knows" that one of the branches will not be executed. This means that your compile-time recursion is not really terminated. It is potentially infinite. It just bottoms out with a compilation error when the compiler attempts to declare an array arr of size 0, which is illegal. This is what triggers the error.
Again, when the compiler generates printArray<1>, it instantiates the code for both branches of the inner if, meaning that it will attempt to declare
int arr[0][0] = {};
which is illegal.
The error message you are getting from your compiler is misleading, probably because your compiler implements some non-standard extensions allowing it to accept zero-sized arrays. In reality the error should be triggered by the zero-sized array declaration.
If you are trying to implement compile-time template recursion, you have to use compile-time techniques (as opposed to run-time branching) to make it bottom out. In your case it can be done by using explicit specialization, i.e. by adding a separate explicitly specialized non-recursive version of printArray for arrays of size 1.
template<>
void printArray<1>(int (*iarr)[1]) {
}
(I don't know why you are not doing anything for arrays of size 1, I just faithfully reproduced your intended functionality.)
Alternatively, you can achieve the same effect by using ordinary function overloading instead of explicit template specialization. Declare this overloaded version
void printArray(int (*iarr)[1]) {
}
and it will solve the problem as well. (Just remember that in this case it has to be declared before the recursive printArray template).
Of course, now you no longer need branching inside your recursive version
template<int size>
void printArray(int (*iarr)[size]) {
const int s = size - 1;
cout << size << endl;
int arr[s][s] = {};
printArray<s>(arr);
}
P.S. And there's no need to specify the template argument of printArray explicitly in your code sample. You can just call your function as printArray(arr). The compiler will deduce the size.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With