在模板化函数

时间:2016-02-25 19:09:12

标签: c++ arrays loops metaprogramming c++17

说我有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的位置,vecstatdyn。但我希望能够通过再次传递X来在模板中执行此操作。我需要做的是:

  1. 包含的类型
  2. 容器尺寸
  3. 我能在以下函数中得到它吗?

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

    或者我无法从unique_ptr中提取尺寸信息?或者以通用的方式输入? (我已经将这个问题标记为C ++ 17,希望可以使用size。)

3 个答案:

答案 0 :(得分:2)

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

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

这是一个指针,我们丢失了大小信息。对于唯一指针,所有数组重载都会将销毁中的delete调用更改为delete[]。如果你想使用unique_ptr“数组”那么你将需要传递大小。

答案 1 :(得分:2)

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

但是任何其他容器,你甚至不需要size()。只需C ++ 11即可:

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

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

答案 2 :(得分:1)

如果您使用相应内容的循环,那么您实际上并不关心实际的容器或持有者。这是使用一对迭代器,数组视图或范围的好时机。 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);

请注意,您必须在std::unique_ptr<int[]>案例中对大小3进行硬编码,或者在变量中的某处自己跟踪它。否则无法提供尺寸信息。