Work with unique_ptr<int[]>, vector<int>, and int[] in a Templatized Function

こ雲淡風輕ζ 提交于 2019-12-24 12:06:10

问题


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:

  1. The contained type
  2. 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.)


回答1:


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.




回答2:


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.




回答3:


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.



来源:https://stackoverflow.com/questions/35636160/work-with-unique-ptrint-vectorint-and-int-in-a-templatized-function

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!