在模板化函数中使用 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;
其中 X
是 vec
、stat
或 dyn
。但我希望能够通过再次传入 X
在模板中执行此操作。为此,我需要的是:
- 包含的类型
- 容器大小
我可以在这样的函数中得到它吗:
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 进行硬编码,要么在变量中的某处自行跟踪它。否则无法获得尺码信息。
假设我有 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;
其中 X
是 vec
、stat
或 dyn
。但我希望能够通过再次传入 X
在模板中执行此操作。为此,我需要的是:
- 包含的类型
- 容器大小
我可以在这样的函数中得到它吗:
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 进行硬编码,要么在变量中的某处自行跟踪它。否则无法获得尺码信息。