Mq-b/Modern-Cpp-templates-tutorial

对形参包展开场所的补充

Closed this issue · 7 comments

C++ 只允许在这几种语境下进行形参包展开

对于01函数模板使用的几个例子:

  •   template<typename...Args>
      void print(const Args&...args){    
          int _[]{ (std::cout << args << ' ' ,0)... };
      }

    是在花括号包围的初始化器中展开

  •   template<typename T,std::size_t N, typename...Args>
      void f(const T(&array)[N], Args...index) {
          print(array[index]...);
      }

    是在函数形参列表中展开

所以不能以如下方式通过形参包展开输出所有参数而要使用前面那种看起来有点奇怪的方式

template<typename ...Args>
void print(const Args &...args) {
    (std::cout << args << " ")...;
}
  template<typename...Args>
  void print(const Args&...args){    
      int _[]{ (std::cout << args << ' ' ,0)... };
  }

@Mq-b 我在想这个例子是否应该支持空参数列表(print())?目前这个写法在参数列表为空时会导致 _ 为非良构的 0 长度数组,在严格的模式下造成编译错误。

解决方案是在数组中添加一个元素使其长度始终为正。

  template<typename...Args>
  void print(const Args&...args){    
-      int _[]{ (std::cout << args << ' ' ,0)... };
+      int _[]{ 0, (std::cout << args << ' ' ,0)... };
  }
Mq-b commented

@frederick-vs-ja 有道理,唉,要考虑的东西真多。

Mq-b commented
  template<typename...Args>
  void print(const Args&...args){    
      int _[]{ (std::cout << args << ' ' ,0)... };
  }

@Mq-b 我在想这个例子是否应该支持空参数列表(print())?目前这个写法在参数列表为空时会导致 _ 为非良构的 0 长度数组,在严格的模式下造成编译错误。

解决方案是在数组中添加一个元素使其长度始终为正。

  template<typename...Args>
  void print(const Args&...args){    
-      int _[]{ (std::cout << args << ' ' ,0)... };
+      int _[]{ 0, (std::cout << args << ' ' ,0)... };
  }

我又想了一下,我为什么要允许空参(print())调用呢?至少这里完全没必要,不过出于教学目的,可以提及一下。

Mq-b commented
  template<typename...Args>
  void print(const Args&...args){    
+      int _[]{ 0, (std::cout << args << ' ' ,0)... };
  }

其实我还觉得有点神奇,{ 0, (std::cout << args << ' ' ,0)... } 如果形参包为空,编译器还会去掉 0 后面那个逗号。

其实我还觉得有点神奇,{ 0, (std::cout << args << ' ' ,0)... } 如果形参包为空,编译器还会去掉 0 后面那个逗号。

不需要去掉,花括号初始化器列表一直都允许有一个尾随的逗号。从古代 C++ 起 int a[] = {0, }; 就是合法的定义。

Mq-b commented

其实我还觉得有点神奇,{ 0, (std::cout << args << ' ' ,0)... } 如果形参包为空,编译器还会去掉 0 后面那个逗号。

不需要去掉,花括号初始化器列表一直都允许有一个尾随的逗号。从古代 C++ 起 int a[] = {0, }; 就是合法的定义。

没用的知识又增加了🤣。

Mq-b commented

找个什么地方补充一下这些,顺便再加个弃值表达式在这的运用,转换到 void