Hi all,
I'm trying to do something with templates, but I'm running into problems. I want to write an array class and write a constructor that takes N arguments, where N is length of the array:
1 2 3 4 5
template<int N>
struct Array{
int a[N];
Array(/*I want this to be "int a1, int a2, int a3, ... int aN*/);
};
And there is one odd thing I noticed while looking for a solution. I wrote this function and tested it with Array<10>:
1 2 3 4 5 6 7 8
void Array::Print(){
cout << "this array has" << N << "elements\n";//this line works fine
#if N == 10
cout << "N = 10\n";
#elif N == 0
cout << "N = 0\n"; //however this line shows up
#endif
}
Could someone explain why is this happening? Shouldn't template functions be recompiled for every N? And is there anything I can do about a constructor (other than use ...)?
1. Use boost::array, it allows initialization with initializer list : boost::array<int, 10> = { 1, 2 ... 10 };
If you don't want to use it, you can also mimic how boost::array uses initializer list.
2. While compiling before anything happens, the preprocessor goes through the file, and does it's job. It has no idea what will N contain, and you can't make it know either. The preprocessor symbol N is totally unrelated of the template parameter. If you replace N in #elif N == 0 with any other symbol, the output will be still the same.
To achieve what you want to do, you have to do template specialization :
1 2 3 4 5
template<int N>
void Array<N>::print() { std::cout << "this array hold N elements\n"; }
template<>
void Array<10>::print() { std::cout << "this array hold 10 elements\n"; }
Using varadic functions is very dangerous. How do you know how many parameters were actually passed?
You don't, and the compiler won't complain either if you pass too much or too few arguments, it will only turn out at runtime.
Using the initializer list as boost::array does, gives more safety. The complier will complain when too much arguments were passed, and if too few was passed it will default construct the remaining elements.
Don't forget that c++ provides a mechanism for initializing struct members with an initializer list
(but you can't have a constructor if you want to use this feature):
I hoped there was something like a 'repeat' macro.. C++ preprocessor isn't very flexible, is it?
Oh well, I guess I'll stick with initializer lists, though I wish there was a clean way to initialize an array and use it as function argument in one line.