template模板复习

0.引言


type ... pack-name(optional)	(1)	
typename|class ... pack-name(optional)	(2)	
type-constraint ... pack-name(optional)	(3)	(since C++20)
template < parameter-list > class ... pack-name(optional)	(4)	(until C++17)
template < parameter-list > typename|class ... pack-name(optional)	(4)	(since C++17)

1.包展开

#include<iostream>
//  此时 T  为包名
template <typename... T> //T... -> int,double,char
void fun(T... args){
}
int main(){
  fun<int, double,char>(3,5.3,'c');
}

等价于:

#include<iostream>
template <typename... T> //T... -> int,double,char
void fun(T... args){
}

/* First instantiated from: insights.cpp:6 */
#ifdef INSIGHTS_USE_TEMPLATE
template<>
void fun<int, double, char>(int __args0, double __args1, char __args2)
{
}
#endif

int main()
{
  fun<int, double, char>(3, 5.2999999999999998, 'c');
}

2.(C++17) 折叠表达式

  • 基于逗号的折叠表达式应用

  • 折叠表达式用于表达式求值,无法处理输入(输出)是类型与模板的情形

    #include<iostream>
    
    void fun(){}
    
    template <typename U, typename... T> 
    void fun(U u, T... args){
      std::cout<< u<<std::endl;
      fun(args...);//递归调用,进行展开打印
    }
    int main(){
      fun(1,2,"hello",'c');
    }
    

    等价于:

    #include<iostream>
       void fun()
       {
       }
    
       template <typename U, typename... T> 
       void fun(U u, T... args){
         std::cout<< u<<std::endl;
         fun(args...);//递归调用,进行展开打印
       }
       
       /* First instantiated from: insights.cpp:11 */
       #ifdef INSIGHTS_USE_TEMPLATE
       template<>
       void fun<int, int, const char *, char>(int u, int __args1, const char * __args2, char __args3)
       {
         std::cout.operator<<(u).operator<<(std::endl);
         fun(__args1, __args2, __args3);
       }
       #endif
       
       /* First instantiated from: insights.cpp:8 */
       #ifdef INSIGHTS_USE_TEMPLATE
       template<>
       void fun<int, const char *, char>(int u, const char * __args1, char __args2)
       {
         std::cout.operator<<(u).operator<<(std::endl);
         fun(__args1, __args2);
       }
       #endif
      
       /* First instantiated from: insights.cpp:8 */
       #ifdef INSIGHTS_USE_TEMPLATE
       template<>
       void fun<const char *, char>(const char * u, char __args1)
       {
         std::operator<<(std::cout, u).operator<<(std::endl);
         fun(__args1);
       }
       #endif
       
       
       /* First instantiated from: insights.cpp:8 */
       #ifdef INSIGHTS_USE_TEMPLATE
       template<>
       void fun<char>(char u)
       {
         std::operator<<(std::cout, u).operator<<(std::endl);
         fun();
       }
       #endif
       
       int main()
       {
         fun(1, 2, "hello", 'c');
       }
    
    • 折叠表达式:
    #include<iostream>
    
    template <typename... T> 
    void fun(T... args){
       ((std::cout<<args<<std::endl), ...);
    }
    int main(){
      fun(1,2,"hello",'c');//递归调用,进行展开打印
    }
    

    等价于:

        #include<iostream>
    
    template <typename... T> 
    void fun(T... args){
       ((std::cout<<args<<std::endl), ...);
    }
    
    /* First instantiated from: insights.cpp:8 */
    #ifdef INSIGHTS_USE_TEMPLATE
    template<>
    void fun<int, int, const char *, char>(int __args0, int __args1, const char * __args2, char __args3)
    {
      (std::cout.operator<<(__args0).operator<<(std::endl)) , 
      ((std::cout.operator<<(__args1).operator<<(std::endl)) , 
      ((std::operator<<(std::cout, __args2).operator<<(std::endl)) ,
       (std::operator<<(std::cout, __args3).operator<<(std::endl))));
    }
    #endif
    
    int main()
    {
      fun(1, 2, "hello", 'c');
    }
    

    例2:

    #include<iostream>
    
    template<typename ...Args>
    int sum(Args&&... args) {
      return (args + ... ); // OK
    }
    
    template<typename ...Args>
    int sum(Args&&... args) {
      return (... + args); // OK
    }
    int main(){
      std::cout<< sum(1,2,3,4,5)<<std::endl;//15
    }
    

    等价于:

        #include<iostream>
    
    template<typename ...Args>
    int sum(Args&&... args) {
      return (args + ... ); // OK
    }
    
    /* First instantiated from: insights.cpp:9 */
    #ifdef INSIGHTS_USE_TEMPLATE
    template<>
    int sum<int, int, int, int, int>(int && __args0, 
    							    int && __args1, int && __args2, 
    							    int && __args3, int && __args4)
    {
      return __args0 + (__args1 + (__args2 + (__args3 + __args4)));
    }
    #endif
    
    
    int main()
    {
      std::cout.operator<<(sum(1, 2, 3, 4, 5)).operator<<(std::endl);
    }
    
    

3.完美转发

  • (C++11) 完美转发: std::forward 函数

  • 通常与万能引用结合使用

  • 同时处理传入参数是左值或右值的情形

    #include<iostream>
    
    void g(int&){
      std::cout<<"l-reference\n";
    }
    void g(int&&){
      std::cout<<"r-reference\n";
    }
    int main(){
      int x = 3;
      g(x);//l-reference
      g(4);//r-reference
    }
    
    #include<iostream>
    
    void g(int&){
      std::cout<<"l-reference\n";
    }
    void g(int&&){
      std::cout<<"r-reference\n";
    }
    template<typename T>
    void fun(T input){
    void fun(T&& input){//万能引用,相同的结果
      std::cout<<"Hello\n";
      g(input);
    }
    int main(){
      int x = 3;
      fun(x);//Hello\nl-reference
      fun(4);//Hello\nl-reference 
      - T input 变为了左值,这并不是我们想要的结果,我们想要的是r-reference
    }
    

    解决:完美转发

    #include<iostream>
    #include<utility>
    
    void g(int&){
     std::cout<<"l-reference\n";
    }
    void g(int&&){
     std::cout<<"r-reference\n";
    }
    template<typename... T>
    void fun(T&&... args){
     std::cout<<"Hello\n";
     g(std::forward<T>(args)...);
    }
    int main(){
     int x = 3;
     fun(x);//Hello\nl-reference
     fun(4);//Hello\nr-reference 
    }
    

4.变量模板

  • template T pi = (T)3.1415926;

  • 其它形式的变量模板

    #include<iostream>
    #include<utility>
    template <typename T> 
    T pi = (T)3.1415926;
    
    int main(){
      std::cout<< pi<float> <<std::endl;//3.1415926
      std::cout<< pi<int> <<std::endl;//3
    }
    
    #include<iostream>
    #include<utility>
    template <typename T> 
    unsigned MySize = sizeof(T);
    
    int main(){
      std::cout<< MySize<float> <<std::endl;//4
      std::cout<< MySize<int> <<std::endl;//4
    }
    
    #include<iostream>
    #include<utility>
    template <typename T, unsigned v> 
    unsigned MySize = (sizeof(T) == v);
    
    int main(){
      std::cout<< MySize<float, 4> <<std::endl;//1
      std::cout<< MySize<int, 2> <<std::endl;//0
    }
    

    is_same_v就是一个变量模板

    template< class T, class U >
    inline constexpr bool is_same_v = is_same<T, U>::value;
    
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值