zoukankan      html  css  js  c++  java
  • Variadic Template

    Variadic Template

    谈的是 template

    • function template
    • class template

    变化的是 template parameters

    • 参数个数 (variadic number) --- 利用参数个数逐一递减的特性,实现递归函数调用,使用 function template 完成
    • 参数类型 (different type) --- 利用参数个数逐一递减的特性导致参数类型逐一递减,实现递归继承或递归复合,用 class template 来完成
    void func() {···}
    
    template<typename T, typename ... Types>
    void func(const T& firstArg, const Types& ... args) {
        //处理 firstArg
        func(args ...);
    }
    

    利用 function template 来实现函数递归,令函数参数逐一递减,如下:

    #include <iostream>
    using namespace std;
    void print() {
    	
    }
    
    template<typename T, typename ... Types>
    void print(const T& firstArg, const Types& ... args) { // 1
    	
    	print(args ...);
    	cout << firstArg << "	" << sizeof ... (args) << endl; // sizeof ... (args) 可以得知这一包东西 (args) 中还有几个参数。
    } 
    int main(){
    	print(12, 2.2, "hello variadic template!", 'a');
    	return 0;
    }
    

    如果还有另外一个长的差不多的函数,编译器会报错嘛?

    template<typename ... Types>
    void print(const Types& ... args) { // 2
        ···
    }
    

    看似 1 与 2 差不多,那么 print(args ...); 到底是调用 1 还是调用 2 呢?这就要看哪个更加特化,哪个更加泛化。如果使用模板形成了 overload,那么会优先调用更加特化的那个。

    答案是 print(args ...); 会调用 1,也就是说 1 更加特化。我的理解是参考了老子的 “一生二二生三三生万物” 这句话,从这句话中来讲,“一” 是包罗万象的,也就是最泛化的,所以函数 1 更加特化。

    若参数 type 皆同,用 initializer_list 足矣

    #include <iostream>
    using namespace std;
    
    struct iterator_less{
    	
    	
    	template<typename _ForwardIterator>
    	bool operator()(_ForwardIterator _it1, _ForwardIterator _it2) const {
    		return *_it1 < *_it2;
    	}
    };
    
    template<typename _ForwardIterator, typename _Compare>
    _ForwardIterator _elem_max(_ForwardIterator first, _ForwardIterator last, _Compare cmp) {
    	if(first == last)	return first;
    	_ForwardIterator result = first;
    	while(first != last) {
    		if(cmp(result, first)) {
    			result = first;
    		}
    		++first;
    	}
    	return result;
    }
    
    template<typename _ForwardIterator>
    _ForwardIterator elem_max(_ForwardIterator first, _ForwardIterator end) {
    	return _elem_max(first, end, iterator_less());
    }
    
    template<typename T>
    T max(initializer_list<T> _l) {
    	return *elem_max(_l.begin(), _l.end());
    }
    
    // 测试!
    int main(){
    	int max_elem = max({23,1,2,55,6,7,8888}); // 通过 initializer_list 的接口
    	cout << "max elem: " << max_elem << endl;
    	return 0;
    }
    

    如果我不想用 initializer_list 的接口呢?

    接下来就是利用 function template 来实现函数递归调用来使参数逐个递减,最后来调用 std::max(arg1, arg2);

    template<typename T>
    T maximum(T obj) {
        return obj;
    }
    
    template<typename T, typename ... ArgsType>
    T maximum(const T& firstArg, const ArgsType& ... args) {
        return std::max(firstArg, maximum(args ...));
    }
    

    用于递归继承 (recursive inheritance)

    递归调用处理的都是参数,使用 function template

    递归继承处理的是类型,使用 class template

    template<class ... Types>
    class tuple;
    
    template<>
    class tuple<> {};
    
    template<class Head, class ... Tail>
    class tuple<Head, Tail...> : private tuple<Tail...>{
    public:
    	tuple() {}
    	tuple(Head first, Tail... tails) : _obj(first), tuple<Tail...> (tails...) {}
    	Head head() { return _obj; }
    	tuple<Tail...> tail() { return *this; };    // 这里为什么返回 *this ? 需要之后去看书理解,也就是继承类的对象模型到底是长什么样?
    private:
    	Head _obj;
    };
    
    int main(){
    	tuple<int, string, double> t(3, "hello", 3.3);
    	cout << t.head() << endl;
    	cout << t.tail().head() << endl;
    	return 0;
    }
    
  • 相关阅读:
    qiankun 报错:Target container with #container not existed while xxx mounting!
    promise加载队列实现
    promise 封装定时器
    关于promise
    节流防抖
    箭头函数特点
    this
    手写apply
    手写call
    手写bind函数
  • 原文地址:https://www.cnblogs.com/Codroc/p/13998469.html
Copyright © 2011-2022 走看看