Is there a way in C++ to specify any type* as type of a template, for example through a wildcard or some keyword.
I remember in Java we can do that using the ? wildcard as generic type, like HashMap<Long, ?>
.
I try to better explain the question using a sample code. Suppose we have the following Record class:
template<typename T>
class Record
{
private:
T content;
long size;
public:
Record(T _content, long _size)
{
this->content = _content;
this->size = _size;
}
T getContent()
{
return this->content;
}
long getSize()
{
return this->size;
}
};
and suppose we want to use instances of the above class without specifying the exact type (I used the ? in the following class), simply because useless in the case in which the class Computer uses only the method Record::getSize()
:
class Computer
{
public:
long long computeTotalSize(vector<Record<?>> recordVector)
{
long long totalSize = 0;
for (vector<Record<?>>::iterator it = recordVector.begin() ; it != recordVector.end(); ++it)
totalSize += (*it).getSize();
return totalSize;
}
};
extends Record<string, any> is known as generic type constraint, and it allows you to specify that your generic type must be assignable to the type that comes after the extends keyword. In this case, Record<string, any> indicates an object with keys of type string and values of type any .
Generics are syntax components of a programming language that can be reused for different types of objects. Typically, generics take the form classes or functions, which take type(s) as a parameter.
A generic class and a generic method can handle any type of data.
Generic Classes These classes are known as parameterized classes or parameterized types because they accept one or more parameters.
You can make computeTotalSize
a template function with the record template parameter as it's template parameter:
template <typename T>
long long computeTotalSize(vector<Record<T>> recordVector)
{
long long totalSize = 0;
for (vector<Record<T>>::iterator it = recordVector.begin() ; it != recordVector.end(); ++it)
totalSize += (*it).getSize();
return totalSize;
}
Note that you should also pass the vector by reference to avoid copying the entire thing:
long long computeTotalSize(const vector<Record<T>>& recordVector)
It cannot be done the same way as in Java, because C++ templates are fundamentally different from Java generics (C++ templates generate entirely distinct types, not fancy constructs on top a type-erased type). However, you could make computeTotalSize
a function template:
class Computer
{
public:
template <class T>
long long computeTotalSize(const vector<Record<T>>& recordVector)
{
long long totalSize = 0;
for (auto it = recordVector.begin() ; it != recordVector.end(); ++it)
totalSize += it->getSize();
return totalSize;
}
};
Notice I took the liberty of streamlining the syntax of the code somewhat; the only behaviour change is using const&
to pass the vector, to prevent copying it.
Note that the change to const&
requires getSize()
to be marked as a const
member function:
long getSize() const
{
return size;
}
Since it would be highly unexpected for a function called getSize()
to modify the object on which it's called, this is actually a good thing.
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