Mq-b / Modern-Cpp-templates-tutorial

现代C++模板教程
https://mq-b.github.io/Modern-Cpp-templates-tutorial/
Other
662 stars 88 forks source link

对形参包展开场所的补充 #21

Closed Suzukaze7 closed 8 months ago

Suzukaze7 commented 9 months ago

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

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

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

template<typename ...Args>
void print(const Args &...args) {
    (std::cout << args << " ")...;
}
frederick-vs-ja commented 9 months ago
  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 9 months ago

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

Mq-b commented 8 months ago
  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 8 months ago
  template<typename...Args>
  void print(const Args&...args){    
+      int _[]{ 0, (std::cout << args << ' ' ,0)... };
  }

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

frederick-vs-ja commented 8 months ago

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

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

Mq-b commented 8 months ago

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

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

没用的知识又增加了🤣。

Mq-b commented 8 months ago

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