update
This commit is contained in:
		
							
								
								
									
										30
									
								
								README.md
									
									
									
									
									
								
							
							
						
						
									
										30
									
								
								README.md
									
									
									
									
									
								
							@@ -163,7 +163,33 @@ for(decl:col) {
 | 
			
		||||
 | 
			
		||||
- [C++中如何将string类型转换为int类型?](./basic_content/extent/string_int.md)
 | 
			
		||||
 | 
			
		||||
### 5.代码运行
 | 
			
		||||
### 5.自己写的工具
 | 
			
		||||
 | 
			
		||||
- [容器快捷输出工具](./tool/output)
 | 
			
		||||
 | 
			
		||||
对吴老师的代码进行了修改,[点击此处直通代码](./tool/output/output_container.h)
 | 
			
		||||
 | 
			
		||||
输入:
 | 
			
		||||
 | 
			
		||||
```cpp
 | 
			
		||||
map<int, int> mp{
 | 
			
		||||
            {1, 1},
 | 
			
		||||
            {2, 4},
 | 
			
		||||
            {3, 9}};
 | 
			
		||||
    cout << mp << endl;
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
输出结果显示:
 | 
			
		||||
 | 
			
		||||
```cpp
 | 
			
		||||
{ 1 => 1, 2 => 4, 3 => 9 }
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
感谢吴老师的代码,原代码:
 | 
			
		||||
 | 
			
		||||
> https://github.com/adah1972/output_container/blob/master/output_container.h
 | 
			
		||||
 | 
			
		||||
### 6.代码运行
 | 
			
		||||
 | 
			
		||||
- **代码环境**
 | 
			
		||||
 | 
			
		||||
@@ -173,7 +199,7 @@ Ubuntu 18.04
 | 
			
		||||
 | 
			
		||||
CLion  gcc/g++
 | 
			
		||||
 | 
			
		||||
### 6.关于作者
 | 
			
		||||
### 7.关于作者
 | 
			
		||||
 | 
			
		||||
个人公众号:
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										43
									
								
								tool/output/container.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										43
									
								
								tool/output/container.cpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,43 @@
 | 
			
		||||
//
 | 
			
		||||
// Created by light on 19-12-16.
 | 
			
		||||
//
 | 
			
		||||
 | 
			
		||||
#include <iostream>
 | 
			
		||||
#include <map>
 | 
			
		||||
#include <set>
 | 
			
		||||
#include <vector>
 | 
			
		||||
#include "output_container.h"
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
using namespace std;
 | 
			
		||||
 | 
			
		||||
int main() {
 | 
			
		||||
    map<int, int> mp{
 | 
			
		||||
            {1, 1},
 | 
			
		||||
            {2, 4},
 | 
			
		||||
            {3, 9}};
 | 
			
		||||
    cout << mp << endl;
 | 
			
		||||
    vector<vector<int>> vv{
 | 
			
		||||
            {1, 1},
 | 
			
		||||
            {2, 4},
 | 
			
		||||
            {3, 9}};
 | 
			
		||||
    cout << vv << endl;
 | 
			
		||||
 | 
			
		||||
    pair<int, int> p{1, 2};
 | 
			
		||||
    cout << p << endl;
 | 
			
		||||
 | 
			
		||||
    set<int> s{1, 2, 3};
 | 
			
		||||
    cout << s << endl;
 | 
			
		||||
 | 
			
		||||
    vector<char> v{'a', 'b'};
 | 
			
		||||
    cout << v << endl;
 | 
			
		||||
    set<char *> vs{"a", "b"};
 | 
			
		||||
    cout << vs << endl;
 | 
			
		||||
 | 
			
		||||
    map<int, char *> mm{
 | 
			
		||||
            {1,   "23"},
 | 
			
		||||
            {2, "234hi"}
 | 
			
		||||
    };
 | 
			
		||||
    cout << mm << endl;
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										150
									
								
								tool/output/output_container.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										150
									
								
								tool/output/output_container.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,150 @@
 | 
			
		||||
//
 | 
			
		||||
// Created by light on 20-1-8.
 | 
			
		||||
//
 | 
			
		||||
 | 
			
		||||
#ifndef MORDEN_C_OUTPUT_CONTAINER_H
 | 
			
		||||
#define MORDEN_C_OUTPUT_CONTAINER_H
 | 
			
		||||
 | 
			
		||||
#include <ostream>      // std::ostream
 | 
			
		||||
#include <type_traits>  // std::false_type/true_type/decay_t/is_same_v
 | 
			
		||||
#include <utility>      // std::declval/pair
 | 
			
		||||
 | 
			
		||||
// 检测是否是pair
 | 
			
		||||
template<typename T>
 | 
			
		||||
struct is_pair : std::false_type {
 | 
			
		||||
};
 | 
			
		||||
template<typename T, typename U>
 | 
			
		||||
struct is_pair<std::pair<T, U>> : std::true_type {
 | 
			
		||||
};
 | 
			
		||||
template<typename T>
 | 
			
		||||
inline constexpr bool is_pair_v = is_pair<T>::value;
 | 
			
		||||
 | 
			
		||||
// 检测输出函数是否存在
 | 
			
		||||
template<typename T>
 | 
			
		||||
struct has_output_function {
 | 
			
		||||
    template<class U>
 | 
			
		||||
    static auto output(U *ptr)
 | 
			
		||||
    -> decltype(std::declval<std::ostream &>() << *ptr,
 | 
			
		||||
            std::true_type());
 | 
			
		||||
 | 
			
		||||
    template<class U>
 | 
			
		||||
    static std::false_type output(...);
 | 
			
		||||
 | 
			
		||||
    static constexpr bool value =
 | 
			
		||||
            decltype(output<T>(nullptr))::value;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
template<typename T>
 | 
			
		||||
inline constexpr bool has_output_function_v =
 | 
			
		||||
        has_output_function<T>::value;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
enum CHARS {
 | 
			
		||||
    ORD,        // 其他类型
 | 
			
		||||
    CHAR,       // char 类型
 | 
			
		||||
    STRING      // string 类型
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
template<typename T>
 | 
			
		||||
int ischarOrString(T &elem) {
 | 
			
		||||
    using std::decay_t;
 | 
			
		||||
    using std::is_same_v;
 | 
			
		||||
    using element_type = decay_t<decltype(elem)>;
 | 
			
		||||
    constexpr bool is_char_v = is_same_v<element_type, char>;
 | 
			
		||||
    constexpr bool is_string_v = is_same_v<element_type, char *> ||
 | 
			
		||||
                                 is_same_v<element_type, const char *> ||
 | 
			
		||||
                                 is_same_v<element_type, std::string>;
 | 
			
		||||
    if (is_char_v)
 | 
			
		||||
        return CHAR;
 | 
			
		||||
    else if (is_string_v)
 | 
			
		||||
        return STRING;
 | 
			
		||||
    else
 | 
			
		||||
        return ORD;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template<typename T>
 | 
			
		||||
void output(T &elem, int type, std::ostream &os) {
 | 
			
		||||
    switch (type) {
 | 
			
		||||
        case CHAR:
 | 
			
		||||
            os << '\'' << elem << '\'';
 | 
			
		||||
            break;
 | 
			
		||||
        case STRING:
 | 
			
		||||
            os << '\"' << elem << '\"';
 | 
			
		||||
            break;
 | 
			
		||||
        case ORD:
 | 
			
		||||
            os << elem;
 | 
			
		||||
            break;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template<typename T, typename Cont>
 | 
			
		||||
auto output_element(std::ostream &os, const T &element,
 | 
			
		||||
                    const Cont &)
 | 
			
		||||
-> typename std::enable_if<is_pair<typename Cont::value_type>::value, bool>::type {
 | 
			
		||||
    int ftype = ischarOrString(element.first);
 | 
			
		||||
    int stype = ischarOrString(element.second);
 | 
			
		||||
 | 
			
		||||
    output(element.first, ftype, os);
 | 
			
		||||
    os << " => ";
 | 
			
		||||
    output(element.second, stype, os);
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template<typename T, typename Cont>
 | 
			
		||||
auto output_element(std::ostream &os, const T &element,
 | 
			
		||||
                    const Cont &)
 | 
			
		||||
-> typename std::enable_if<!is_pair<typename Cont::value_type>::value, bool>::type {
 | 
			
		||||
    int etype = ischarOrString(element);
 | 
			
		||||
    output(element, etype, os);
 | 
			
		||||
    return false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template<typename T, typename U>
 | 
			
		||||
std::ostream &operator<<(std::ostream &os, const std::pair<T, U> &pr) {
 | 
			
		||||
    os << '(' << pr.first << ", " << pr.second << ')';
 | 
			
		||||
    return os;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//template<typename T, typename Cont>
 | 
			
		||||
//auto output_element(std::ostream& os, const T& element,
 | 
			
		||||
//                    const Cont&, const std::true_type)
 | 
			
		||||
//-> decltype(std::declval<typename Cont::key_type>(), os)
 | 
			
		||||
//{
 | 
			
		||||
//    os << element.first << " => " << element.second;
 | 
			
		||||
//    return os;
 | 
			
		||||
//}
 | 
			
		||||
//
 | 
			
		||||
//template <typename T, typename Cont>
 | 
			
		||||
//auto output_element(std::ostream& os, const T& element,
 | 
			
		||||
//                    const Cont&, ...)
 | 
			
		||||
//-> decltype(os)
 | 
			
		||||
//{
 | 
			
		||||
//    os << element;
 | 
			
		||||
//    return os;
 | 
			
		||||
//}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
// 针对没有输出函数的容器处理
 | 
			
		||||
template<typename T,
 | 
			
		||||
        typename = std::enable_if_t<!has_output_function_v<T>>>
 | 
			
		||||
auto operator<<(std::ostream &os, const T &container)
 | 
			
		||||
-> decltype(container.begin(), container.end(), os) {
 | 
			
		||||
    os << "{ ";
 | 
			
		||||
    if (!container.empty()) {
 | 
			
		||||
        bool on_first_element = true;
 | 
			
		||||
        for (auto elem:container) {
 | 
			
		||||
            if (!on_first_element) {
 | 
			
		||||
                os << ", ";
 | 
			
		||||
            } else {
 | 
			
		||||
                on_first_element = false;
 | 
			
		||||
            }
 | 
			
		||||
            output_element(os, elem, container);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    os << " }";
 | 
			
		||||
    return os;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#endif //MORDEN_C_OUTPUT_CONTAINER_H
 | 
			
		||||
		Reference in New Issue
	
	Block a user