Skip to content

Commit

Permalink
修改卢瑟日经,形参包展开问题
Browse files Browse the repository at this point in the history
  • Loading branch information
Mq-b committed May 27, 2024
1 parent 2a866d9 commit 7e07e4f
Show file tree
Hide file tree
Showing 2 changed files with 18 additions and 12 deletions.
2 changes: 1 addition & 1 deletion src/卢瑟日经/godbolt使用文档.md
Original file line number Diff line number Diff line change
Expand Up @@ -261,4 +261,4 @@ https://godbolt.org/z/hv1ae87j7

- [cppinsights](https://cppinsights.io/) 用于查看编译器处理 C++ 语法之后的代码。
- [quick-bench](https://quick-bench.com/) 对比测试 C++ 代码效率。
- [build-bench](https://build-bench.com/) 对比测试 C++ 代码效率,用法比前面的简单。
- [build-bench](https://build-bench.com/) 对比测试 C++ 代码效率,用法比前面的简单。
28 changes: 17 additions & 11 deletions src/卢瑟日经/形参包展开有6个点?.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@

# C++ 形参包展开有 6 个点?

我们知道 C++ 要想使用可变参数,需要使用到模板中的形参包,而要想得到形参包中的元素,则要进行包展开。例如:
## 前言

我们知道 C++ 要想使用可变参数,需要使用到模板中的形参包,而想要获取形参包中的元素,则要进行包展开。

## 基本包展开

```cpp
template<typename... Args> // 类型形参包
Expand All @@ -18,7 +22,11 @@ void f(Args...args){ // 函数形参包
> [运行](https://godbolt.org/z/MW3KT56fn)测试。
如你所见,这些都是使用了三个点 `...` 进行展开。的确,包展开的语法就是三个点,我之所以会说有 6 个点的情况,那是特殊的,叠加在一起的:
如你所见,这些都是使用了三个点 `...` 进行展开。的确,**包展开的语法就是三个点**。
## 6 个点 `Args......` 的特殊情况
我之所以会说有 6 个点的情况,那是因为在某些特殊情况下会叠加使用:
```cpp
template<class Ret, class... Args>
Expand All @@ -29,26 +37,24 @@ void f(Ret(*func)(Args......)) {

> [运行](https://godbolt.org/z/vdseKb3f1)测试。
如你所见,这里的 **`Args......`** 出现了 6 个点其实不用感到奇怪,记住我们以往教程说的话:
如你所见,这里的 **`Args......`** 出现了 6 个点其实不用感到奇怪,记住我们以往教程说的话:

- **C++ 的类型就和拼图一样。**

既然 C++ 形参包展开的语法只有三个点,那么我们就按照已知的去思考。不知道就先不管后面三个点,假设我们传入了 `void``int` 类型,带入进去。`Ret` 就是 `void``Args...` 展开就是 `int`,那么组合起来是?
既然 C++ 形参包展开的语法只有三个点,那么我们就按照已知的去思考。假设我们传入了 `void``int` 类型,带入进去。`Ret` 就是 `void``Args...` 展开就是 `int`加上没有用到的那 `...` 那么组合起来是?

```cpp
void(*func)(int...)
```

发现了吗?C 语言[变长实参](https://zh.cppreference.com/w/cpp/language/variadic_arguments)罢了,C++11 允许了变长实参的三个点可以不以逗号分隔,不过我们一样也可以分割,也就是原来的函数可以改成
发现了吗?C 语言[**变长实参**](https://zh.cppreference.com/w/cpp/language/variadic_arguments)罢了,C++11 允许了变长实参的三个点可以不以逗号分隔。当然我们也可以继续用逗号分隔,例如

```cpp
template<class Ret, class... Args>
void f(Ret(*func)(Args...,...));
```
中间加了一个逗号,这也是无所谓的。
---
中间加了一个逗号变成了 `...,...`,这也是可以的的。
完整代码:
Expand All @@ -70,9 +76,9 @@ int main() {

## 总结

如你所见,理所应当非常简单,不懂就先用已知的知识带入就好
如你所见,这很简单。开始不理解时,可以先用已有的知识带入思考

这个问题最初是一个粉丝提出来的,[`std::is_function`](https://zh.cppreference.com/w/cpp/types/is_function) 的文档,提供了这个库的平凡实现(虽然目前没有标准库是这样实现的),里面出现了:
这个问题最初是一个粉丝提出来。,在 [`std::is_function`](https://zh.cppreference.com/w/cpp/types/is_function) 的文档中,提供了这个库的一个平凡实现(虽然目前没有标准库是这样实现的),里面出现了:

```cpp
// 对常规函数的特化
Expand All @@ -84,4 +90,4 @@ template<class Ret, class... Args>
struct is_function<Ret(Args......)> : std::true_type {};
```
这样一段。其实注释也说的非常简单直观,不过我们还是要带入理解一下。
如上所示,这里就有 `Args......` 。其实注释也说的非常简单直观,不过我们还是要带入理解一下。

0 comments on commit 7e07e4f

Please sign in to comment.