在模板化函数中使用 unique_ptr<int[]>、vector<int> 和 int[]

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

假设我有 3 个变量:

vector<int> vec(3);
int stat[3];
auto dyn = make_unique<int[]>(3);

如果我知道大小是 3,我可以初始化其中任何一个:

for(auto i = 0; i < 3; ++i) X[3] = i;

其中 Xvecstatdyn。但我希望能够通过再次传入 X 在模板中执行此操作。为此,我需要的是:

  1. 包含的类型
  2. 容器大小

我可以在这样的函数中得到它吗:

template <typename T>
void init(T& X);

或者我无法从 unique_ptr 中提取尺寸信息?还是以通用的方式打字? (我已将此问题标记为 C++17,希望可以使用 。)

您将无法从唯一指针获取大小。当您使用 auto dyn = make_unique<int[]>(3); 时,它会被翻译成

make_unique<int[]>(new int[3]())

这是一个指针,我们丢失了大小信息。数组重载对唯一指针所做的全部工作是将销毁中的 delete 调用更改为 delete[]。如果你想使用 unique_ptr "array" 那么你需要传递尺寸。

您不能为 unique_ptr<T[]> 执行此操作 - 它仍然只是一个不知道其大小的原始指针。

但任何其他容器,您甚至不需要 size()。只需 C++11 就足够了:

 template <class T>
 void init(T& container) {
     for (auto& elem : container) {
         elem = 3;
     }
 }

您可以在其上添加 SFINAE 或 static_assert 以确保 T 的元素实际上可分配给 3,否则就足够了。

如果您在各个内容上使用循环,那么您实际上并不关心实际的容器或支架。这是使用一对迭代器、数组视图或范围的好时机。例如:

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);

请注意,您要么必须在 std::unique_ptr<int[]> 情况下对大小 3 进行硬编码,要么在变量中的某处自行跟踪它。否则无法获得尺码信息。