C++模板基础(九)

完美转发与 lambda 表达式模板

void f(int& input)
{
    std::cout << "void f(int& input)\t" << input << '\n';
}

void f(int&& input)
{
    std::cout << "void f(int&& input)\t" << input << '\n';
}

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    int x = 3;
    f(x); //int&
    f(5); //int&&

    return a.exec();
}

在这里插入图片描述

void f(int& input)
{
    std::cout << "void f(int& input)\t" << input << "\n\n";
}

void f(int&& input)
{
    std::cout << "void f(int&& input)\t" << input << "\n\n";
}

template<typename T>
void fun(T input)
//void fun(T& input) //无法将int x = 3;从int转换为int&
//void fun(T&& input) //&&是万能引用,右值引用的变量是左值。输出同void fun(T input)
{
    std::cout << "template<typename T> void fun(T input)\n";
    f(input);
}

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    int x = 3;
    fun(x); //int&
    fun(5); //参数是int&&类型,但是调用了void f(int& input)

    return a.exec();
}

在这里插入图片描述

● (C++11) 完美转发: std::forward 函数
– 通常与万能引用结合使用
– 同时处理传入参数是左值或右值的情形

#include<utility>

void f(int& input)
{
    std::cout << "void f(int& input)\t" << input << "\n\n";
}

void f(int&& input)
{
    std::cout << "void f(int&& input)\t" << input << "\n\n";
}

template<typename T>
void fun(T&& input)
{
    std::cout << "template<typename T> void fun(T input)\n";
    f(std::forward<T>(input)); //完美转发
}
int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    int x = 3;
    fun(x); //int&,调用void f(int& input)
    fun(5); //int&&,调用void f(int&& input)

    return a.exec();
}

在这里插入图片描述

void f(int& input)
{
    std::cout << "void f(int& input)\t" << input << "\n\n";
}

void f(int&& input)
{
    std::cout << "void f(int&& input)\t" << input << "\n\n";
}

template<typename T>
void fun(T input)
{
    std::cout << "template<typename T> void fun(T input)\n";
    f(std::forward<T>(input)); //完美转发不能处理的情形
}
int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    int x = 3;
    fun(x); //int&,调用void f(int&& input)
    fun(5); //int&&,调用void f(int&& input)

    return a.exec();
}

在这里插入图片描述

void f(int& input)
{
    std::cout << "void f(int& input)\t" << input << "\n\n";
}

void f(int&& input)
{
    std::cout << "void f(int&& input)\t" << input << "\n\n";
}

template<typename... T>
void fun(T... inputs)
{
    std::cout << "template<typename... T> void fun(T... inputs)\n";
    f(std::forward<T>(inputs)...); //包展开技术
}
int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    int x = 3;
    fun(x); //int&,调用void f(int&& input)
    fun(5); //int&&,调用void f(int&& input)

    return a.exec();
}

在这里插入图片描述

void f(int& input)
{
    std::cout << "void f(int& input)\t" << input << "\n\n";
}

void f(int&& input)
{
    std::cout << "void f(int&& input)\t" << input << "\n\n";
}

template<typename... T>
void fun(T&&... inputs) //万能引用参数包
{
    std::cout << "template<typename... T> void fun(T... inputs)\n";
    f(std::forward<T>(inputs)...); //包展开技术
}
int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    int x = 3;
    fun(x); //int&,调用void f(int& input)
    fun(5); //int&&,调用void f(int&& input)

    return a.exec();
}

在这里插入图片描述
(C++20) lambda表达式模板

消除歧义与变量模板

struct Str
{
    const static int internal = 3;
};

int p = 5;

template<typename T>
void fun()
{
    //internal是T中的一个具体数据,乘以变量p
    std::cout << T::internal*p << '\n';
}

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);
    
    fun<Str>();
    
    return a.exec();
}

在这里插入图片描述
● 使用 typename 与 template 消除歧义
– 使用 typename 表示一个依赖名称是类型而非静态数据成员

struct Str
{
    using internal = int;
};

template<typename T>
void fun()
{
    //internal是T中的一个数据类型,p是该类型的一个指针
    int x = 5;
    typename T::internal* p = &x; //加上typename表示internal是T中的一个数据类型,消除了歧义
    Str::internal* ptr = &x; //加上限定名Str消除歧义
    std::cout << p << '\n' << ptr << '\n';
}
int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    fun<Str>();

    return a.exec();
}

在这里插入图片描述

– 使用 template 表示一个依赖名称是模板
– template 与成员函数模板调用

struct Str
{
    template<typename T>
    static void internal()
    {
        std::cout << "Str::template<typename T> static void internal()\n";
    }
};

template<typename T>
void fun()
{
    //T::internal<int>(); //编译器可能认为<是小于运算符。Warning: Use 'template' keyword to treat 'internal' as a dependent template name
    T::template internal<int>(); //OK,使用了template消除了歧义
}
int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    fun<Str>();

    return a.exec();
}

在这里插入图片描述

struct Str
{
    template<typename T>
    void internal() //非static函数
    {
        std::cout << "Str::template<typename T> static void internal()\n";
    }
};

template<typename T>
void fun()
{
    T obj;
    //obj.internal<int>(); //编译器可能认为<是小于运算符。Warning: Use 'template' keyword to treat 'internal' as a dependent template name
    obj.template internal<int>();  //OK,使用了template消除了歧义
}
int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    fun<Str>(); //输出同上

    return a.exec();
}

● (C++14) 变量模板
– template T pi = (T)3.1415926;

template<typename T>
T pi = (T)3.141592653;

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    std::cout << pi<double> << '\n';
    std::cout << pi<float> << '\n';
    std::cout << pi<int> << '\n';

    return a.exec();
}

在这里插入图片描述

template<typename T, unsigned v>
unsigned MySize = (sizeof(T) == v);

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    std::cout << MySize<float, 4> << '\n';
    std::cout << MySize<int, 2> << '\n';

    return a.exec();
}

– 其它形式的变量模板
std::is_same

参考
深蓝学院:C++基础与深度解析
cppreference

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值