突发奇想
既然这个cout对象可以直接输出普通内置类型变量的值,还有自定义类类型也玩过;那么可以不可以使用cout直接输出内置数组的各个元素的值呢?比如像这样:
1
2
3
4
5
6
7
8
9
| #include <iostream>
int main() {
int arr[] = {1, 2, 343, 4, 56, 76,82};
std::cout << arr << std::endl;
return 0;
}
|
输出结果可以是:
普通方法
首先,内置数组的元素是可以变化的,那么为了适应不同的元素类型,需要一个函数模板,接收不同内置数组类型;其次就是数组元素必须已知,函数模板中需要一个固定参数保存数组元素大小的值。
- 元素类型为T
- 那么数组的类型就是T[N]
- 加上引用和const就是const T(&arr)[N]
1
2
3
4
5
6
7
8
9
10
11
12
| template <typename T, size_t N>
std::ostream& operator<<(std::ostream& os, const T (&arr)[N]) {
os << "[";
for (int i = 0; i < N - 1; ++i) {
os << arr[i] << ",";
}
os << arr[N - 1] << "]";
return os;
}
|
既然要求是输出结果是[字符开头和]字符结尾,那么可以在模板函数内以字符串的形式输出,但是遇到了一个问题,看一下clangd的错误提示:
1
| Use of overloaded operator '<<' is ambiguous (with operand types 'std::ostream' (aka 'basic_ostream<char>') and 'const char[2]')
|
在提示中可以发现,在os « “[”; 这行代码中,在匹配"[“这个字符串类型的时候,匹配到了两个都符合的«运算符重载函数,此时,编译器会不知道选择哪一个,所以会产生二义性。二义性的原因就是右操作数匹配了多种类型。一个是编译器内置实现的basic_ostream,其实就是const char*,还有一个就是const char[2];第二个就是当前实现的«运算符重载函数,它也直接匹配到了,若没有编译器内置实现的函数的话,那么会一直递归调用当前实现的«运算符重载函数,有的话就产生二义性。那么该如何解决呢?
可以通过强制类型转换的方式去强制它匹配到一个«运算符重载函数,那么强转为const char[2]可以吗?绝对是不可以的,因为这会一直递归调用当前自定义实现的«运算符重载函数,那么只有将其转换为const char*了,修改以上的代码为:
1
2
3
4
5
6
7
8
9
10
11
12
| template <typename T, size_t N>
std::ostream& operator<<(std::ostream& os, const T (&arr)[N]) {
os << reinterpret_cast<const char*>("[");
for (int i = 0; i < N - 1; ++i) {
os << arr[i] << reinterpret_cast<const char*>(",");
}
os << arr[N - 1] << reinterpret_cast<const char*>("]");
return os;
}
|
查看输出结果: