I am just learning how to use templates in c , and I am struggling a bit. I have an example below, with comments at the points where I'm getting hung up.
#include <iostream>
using namespace std;
template<int arrayOneSize, int arrayTwoSize>
class myClass{
public:
myClass(){
for(int i = 0; i < arrayOneSize; i ){
arrayOne[i] = i;
}
for(int i = 0; i < arrayTwoSize; i ){
arrayTwo[i] = i;
}
}
int arrayOne[arrayOneSize];
int arrayTwo[arrayTwoSize];
void printArrayElements(){
for(int i = 0; i < arrayOneSize; i ){
cout << arrayOne[i] << '\n';
}
for(int i = 0; i < arrayTwoSize; i ){
cout << arrayTwo[i] << '\n';
}
}
void someOtherFunction();
};
// can't figure out how to define constructors or functions outside of class
void myClass::someOtherFunction(){
}
template <int numInstances>
class myClassContainer{
public:
myClassContainer(){
for(int i = 0; i < numInstances; i ){
myClassInstances[i] = NULL;
}
}
// this doesn't work
template<int, int> myClass<int, int> *myClassInstances[numInstances];
// also doesn't work
void addClassInstance(myClass *instance){
for(int i = 0; i < numInstances; i ){
if(myClassInstances[i] == NULL){
myClassInstances[i] = instance;
}
}
}
void printAll(){
for(int i = 0; i < numInstances; i ){
myClassInstances[i]->printArrayElements();
}
}
};
int main()
{
myClass<5,6> myClass1;
myClass<1,4> myClass2;
myClassContainer<2> container;
container.addClassInstance(&myClass1);
container.addClassInstance(&myClass2);
container.printArrayElements();
return 0;
}
I would like to be able to pass pointers to myClass instances into myClassContainer, but I can't figure out the template syntax. Thanks in advance for any advice.
CodePudding user response:
can't figure out how to define constructors or functions outside of class
void myClass::someOtherFunction(){}
The problem here is that there is no class called myClass
. Instead, there are only classes called myClass<someNumber, anotherNumber>
. So, in order to define someOtherFunction
, it must be written something like:
void myClass<someNumber, anotherNumber>::someOtherFunction() { ... }
However, neither someNumber
nor anotherNumber
are a concrete number, so you need to make them template parameters:
template<int someNumber, int anotherNumber>
void myClass<someNumber, anotherNumber>::someOtherFunction() { ... }
Also note, it's more common and convenient to use the same template names as the ones used in the class declaration, so your definition would be:
template<int arrayOneSize, int arrayTwoSize>
void myClass<arrayOneSize, arrayTwoSize>::someOtherFunction() { ... }
this doesn't work
template<int, int> myClass<int, int> *myClassInstances[numInstances];
The problem here is that the types of all class member must be known at the time the class was defined. So you can not have a member with a template class that cannot deduce its type at the time the outer class is defined. So you need to either:
- Assign both template parameters with some concrete value:
template <int numInstances>
class myClassContainer{
myClass<2, 3> *myClassInstances[numInstances];
};
- You can use the template parameter of
myClassContainer
to calculate a value:
myClass<numInstances, numInstances * 2> *myClassInstances[numInstances];
- Or you can make both of them template parameter, and add them to the class template parameters:
template <int numInstances, int A, int B>
class myClassContainer{
myClass<A, B> *myClassInstances[numInstances];
};
- Of course you can do any mixture of them
Do note that whichever approach you decided on, you cannot add both myClass<5, 6>
and myClass<1, 4>
to the same array, since they are not the same type.
also doesn't work
void addClassInstance(myClass *instance)
Once again, myClass
is not a type, instead it must be myClass<someValue, anotherValue>
. So you must add the template parameters to the function:
template<int someValue, int anotherValue>
void addClassInstance(myClass<someValue, anotherValue *instance){ ... }
In case you want to define this outside of the class:
template<int numInstances>
template<int someValue, int anotherValue>
void myClassContainer<numInstances>::addClassInstance(myClass<someValue, anotherValue> *instance)
{ ... }