如果未明确说明尺寸信息,模板函数如何知道尺寸?

时间:2018-03-26 22:49:05

标签: c++ c++11 c++14

template<size_t ROWS, size_t COLS>
void f(const array<array<int, COLS>, ROWS>& arr)
{
   for(size_t r=0; r<ROWS; r++)
       for(size_t c=0; c<COLS; c++)
           //stuff
}

array<array<int, 2>, 3> arr {{{1,2},{3,4},{5,6}}};

f(arr);

这有效但怎么样?模板函数如何计算行和列大小?我在函数调用期间没有传递大小信息。我可以看到模板函数如何计算传入的对象的类型,但是在这种情况下我看不出我的ROWS和COLS是如何赋值的。

这个问题试图用模板来理解这个特例。问题不是询问矢量或存在什么其他数据结构。

2 个答案:

答案 0 :(得分:4)

编译器是模式匹配以使调用工作。您在询问具体案例,但我不确定您的理解问题在哪里,所以我将逐步说明

在下面的示例中,我使用f i来呼叫int。编译器推导出T = int以使调用工作。您可能会说&#34;当我没有通过该类型信息时,它如何知道int。&#34;但是你没有明确地在模板参数列表中:

template <typename T>
void f(T t) {
}

int main() {
  int i = 1;
  f(i); // deduces T = int
}

为了更进一步,编译器可以推导出两个不同向量参数的T是什么。对f下面的调用有效,因为编译器可以将std :: vector模式与我传入的参数匹配:

template <typename T>
void f(std::vector<T> v) {
}

int main() {
  std::vector<int> v1;
  f(v1); // deduces T = int

  std::vector<std::string> v2;
  f(v2); // deduces T = std::string
}

在下一个例子中,我创建了一个只有一个参数的类,它是一个size_t,编译器仍能匹配Cls<I>模式

template <std::size_t N>
class Cls { };

template <std::size_t I>
void f(Cls<I> v) {
}

int main() {
  Cls<3> c1;
  f(c1); // deduces I = 3

  Cls<100> c2;
  f(c2); // deduces I = 100
}

std::array版本的工作方式相同,只有std::array涉及的另一个显式模板参数:

template <std::size_t I>
void f(std::array<int, I> v) {
}

int main() {
  std::array<int, 3> a1;
  f(a1); // deduces I = 3

  std::array<int, 100> a2;
  f(a2); // deduces I = 100
}

令人印象深刻的是,即使有多个模板参数嵌套为原始示例,编译器也可以仍然查看参数并匹配模式:

template<size_t ROWS, size_t COLS>
void f(std::array<std::array<int, COLS>, ROWS> arr) {
}

int main() {
  std::array<std::array<int, 2>, 3> arr{};
  f(arr); // deduces COLS = 2 and ROWS = 3 !!
}

在上面的示例中添加const&仍然有效,模式更复杂,但编译器仍然可以匹配它。什么时间活着!

答案 1 :(得分:3)

大小嵌入std::array。由于大小是std::array类型签名的一部分,因此该信息将传递给f。请注意,std::array<int, 2>std::array<int, 3>是完全不同的类型,无法隐式转换为彼此。