Say that I have 3 variables:
vector<int> vec(3);
int stat[3];
auto dyn = make_unique<int[]>(3);
I can initialize any of these if I know the size is 3:
for(auto i = 0; i < 3; ++i) X[3] = i;
Where X
is either, vec
, stat
, or dyn
. But I'd like to be able to do this in a template just by passing in X
again. What I'd need in order to do this is:
- The contained type
- The container size
Can I get that in a function like:
template <typename T>
void init(T& X);
Or am I unable to extract size information from the unique_ptr
? Or type in a universal fashion? (I've marked this question C++17 in the hopes that size
can be used.)
You are not going to be able to get the size from the unique pointer. When you use auto dyn = make_unique<int[]>(3);
it gets translated to
make_unique<int[]>(new int[3]())
Which is a pointer and we lose the size information. All the array overload does for unique pointer is change the delete
call in the destruction to delete[]
. If you want to use an unique_ptr
"array" then you wil need to pass the size.
You can't do this for unique_ptr<T[]>
- that's still just a raw pointer that doesn't have any idea what its size is.
But any other container, you don't even need size()
. Just C++11 suffices:
template <class T>
void init(T& container) {
for (auto& elem : container) {
elem = 3;
}
}
You can add SFINAE or a static_assert
on top of that to ensure that the elements of T
are actually assignable to 3
, but otherwise that suffices.
If you’re using a loop over the respective contents, then you actually don’t care for the actual containers or holders. This is a good time to be using a pair of iterators, an array view, or a range. E.g.:
template<typename It>
void init(It first, It last)
{
// or use an algorithm, e.g. std::iota(first, last, 0)
int i = 0;
for(; first != last; ++last, ++i) *first = i;
}
// use as:
using std::begin;
using std::end;
init(begin(vec), end(vec));
init(begin(stat), end(stat));
init(dyn.get(), dyn.get() + 3);
Note that you either have to hardcode the size 3 in the std::unique_ptr<int[]>
case, or keep track of it yourself somewhere in a variable. The size information is not available otherwise.