【足迹C++primer】59、模板左值右值的转换

模板左值右值的转换

/**
* 功能:模板左值右值的转换
* 时间:2014年7月27日08:18:06
* 作者:cutter_point
*/

#include<iostream>
#include<algorithm>
#include<utility>

using namespace std;

template<typename It>
auto fcn(It beg, It end) -> typename remove_reference<decltype(*beg)>::type
{
    return *beg;    //这里返回的是beg的一个拷贝,因为用了remove_reference去除了引用
}

/**************************************
Function Pointers and Argument Deduction
**************************************/
template<typename T>
int compare(const T &, const T &){cout<<"template<typename T>int compare(const T &, const T &)"<<endl;}

//分别实例化成int compare(const string &, const string &)作为func的参数
void func(int(*)(const string &, const string &)){cout<<"void func(int(*)(const string &, const string &))"<<endl;}
//分别实例化成int compare(const int &, const int &)作为func的参数
void func(int(*)(const int &, const int &)){cout<<"void func(int(*)(const int &, const int &))"<<endl;}

void fun1()
{
    int (*pf1)(const int &, const int &)=compare;   //吧compare实例化成int compare(const int &, const int &)
    func(compare<int>);

}

/**************************************
Template Argument Deduction and References
**************************************/

/**
Type Deduction from Lvalue Reference Function Parameters
*/

/*
见word文档
*/

/**
Type Deduction from Rvalue Reference Function Parameters
*/

/*
见word文档
*/

/**
Writing Template Functions with Rvalue Reference Parameters
写一个模板函数带有右值引用参数
*/

template<typename T>
T fcn2(T &t)
{
    cout<<"t的值是:"<<t<<endl;
    return t;
}

template<typename T>
void f3(T &&val)
{
    T t=val;
    t=fcn2(t);
    if(val == t)
    {
        cout<<"void f3(T &&val),val == t"<<endl;
    }
}

/**************************************
Understanding std::move
**************************************/
/**
std::move如何定义
*/
//remove_reference去除类型中的引用
template<typename T>
typename remove_reference<T>::type &&move(T &&t)//右值
{
    //static_cast就相当于显示地类型转换,百度百科里面是这样
    /*
    int i;
    float   f=166.71;
    i=static_cast<int>(f);
    结果i是166
    */
    return static_cast<typename remove_reference<T>::type &&>(t);   //都是右值!!
}

void fun2()
{
    string s1("hi!"), s2;
    s2=std::move(string("bye!"));   //ok:从一个右值移动
    cout<<"s2=std::move(string(bye!));s2:"<<s2<<endl;
    s2=std::move(s1);   //执行之后s1有不定值
    cout<<"s2=std::move(s1);s2:"<<s2<<"\n"
        <<"s2=std::move(s1);s1:"<<s1<<endl;
}

/**************************************
Forwarding
**************************************/
template<typename F, typename T1, typename T2>
void flip1(F f, T1 t1, T2 t2)
{
    f(t1, t2);
}

void f(int v1, int &v2) //v2是一个引用
{
    cout<<v1<<" "<<++v2<<endl;
}

void fun3()
{
    int i,j=1;
    f(42, i);
    cout<<"f(42, i);i:"<<i<<endl;
    flip1(f, j, 42);
    cout<<"flip1(f, j, 42);j:"<<j<<endl;
}

/**
Defining Function Parameters That Retain Type Information
*/
template<typename F, typename T1, typename T2>
void flip2(F f, T1 &&t1, T2 &&t2)   //两个都是右值引用!!
{
    f(t1, t2);  //吧t1+1输出。两个右值引用,那么t1和t2的值是变了的
}

void fun4()
{
    flip2(f, 8, 8);
    cout<<"flip2(f, i, j);j:"<<endl;
}

/**
Using std::forward to Preserve Type Information in a Call
*/
/*
这里forward返回的是一个右值引用,会改变值的大小
*/
template<typename F, typename T1, typename T2>
void flip(F f, T1 &&t1, T2 &&t2)
{
    f(std::forward<T1>(t1), std::forward<T2>(t2));
}

void fun5()
{
    int j=8;
    flip(f, j, j);  //这里和上面有点不同了,注意这里第二个j要填左值参数,因为在f里面将第二个j的值改变了
    //所以这里虽然传的是形参,但是forward把它还原成右值引用了,还是会改变大小
    cout<<"flip(f, i, j);j:"<<j<<endl;
}

int main()
{
    cout<<">>------------------------------fun1-----------------------------------<<"<<endl;
    fun1();
    cout<<">>------------------------------fun2-----------------------------------<<"<<endl;
    fun2();
    cout<<">>------------------------------fun3-----------------------------------<<"<<endl;
    fun3();
    cout<<">>------------------------------fun4-----------------------------------<<"<<endl;
    fun4();
    cout<<">>------------------------------fun5-----------------------------------<<"<<endl;
    fun5();

    system("pause");
    return 0;
}

【足迹C++primer】59、模板左值右值的转换

时间: 2024-10-05 23:36:46

【足迹C++primer】59、模板左值右值的转换的相关文章

表达式左值右值

左值右值是表达式的属性,该属性称为 value category.按该属性分类,每一个表达式属于下列之一: lvalue left value,传统意义上的左值 xvalue expiring value, x值,指通过“右值引用”产生的对象 prvalue pure rvalue,纯右值,传统意义上的右值(?) 而 xvalue 和其他两个类型分别复合,构成: lvalue + xvalue = glvalue general lvalue,泛左值 xvalue + prvalue = rva

C++ 左值 右值

最近在研究C++ 左值 右值,搬运.收集了一些别人的资料,供自己记录和学习,若以后看到了更好的解释,会继续补充.(打“?”是我自己不明白的地方 ) 参考:<Boost程序库探秘——深度解析C++准标准库(第2版)> 9787302342731 左值:一个可以用来存储数据的变量,有实际的内存地址(变量名): 右值(非左值):“匿名”的“临时”变量,在表达式结束时生命周期终止,不能存放数据,可被修改,也可不被修改(const修饰). 鉴别左值右值: 左值可用取地址操作符&获取地址,右值不行

C++中的左值右值

对于 C++ 中的左值和右值,我们通常的说法是:当一个对象被用作右值的时候,用的是对象的值(内容):当对象被用作左值的时候,用的是对象的身份(在内存中的位置),这句话来自于 <C++ Primer 第五版> 第 121 页,那么,对于这句话,该作何理解呢?下面我想来谈谈我的看法: ISO C++03规定表达式必须是左值或右值之一,而在ISO C++11中,左值性被正式地扩充为更复杂的值类别,对于一个变量来说,与它相关的有两个部分:一是变量在内存中的地址,二是这个变量在内存中的地址中所存储的数据

C++11之右值引用:从左值右值到右值引用

C++98中规定了左值和右值的概念,但是一般程序员不需要理解的过于深入,因为对于C++98,左值和右值的划分一般用处不大,但是到了C++11,它的重要性开始显现出来. C++98标准明确规定: 左值是可以取得内存地址的变量. 非左值即为右值. 从这里可以看出,可以执行&取地址的就是左值,其他的就是右值. 这里需要明确一点,能否被赋值不是区分C++左值和右值的区别. 我们给出四个表达式: string one("one"); const string two("two&

C、C++差异之左值右值

C与C++在语法细节上还是有一些差异的,虽然一般情况下可能这些差异不足以造成结果的区别,但有些代码确实会有影响. 这次,主要总结下左值右值的差异. 在C中,很多左值运算符的结果都不再是左值,然而在C++中,只要逻辑上可行,左值运算符的结果仍然是左值.C++的这种方式,让运算符表达式之间的灵活性更大. 1.++i, 我们都习惯了在C++中,i 自加后返回自己:然而在C中i自加后,返回的是个临时的副本,即和i++是一样的,此结果不能作为左值,即(++i)=0非法.所以我想这就是为什么代码 中还是很多

左值右值(转)

原文链接:http://blog.csdn.net/csdnji/article/details/169200 左值(lvalue)和右值(rvalue)是编程中两个非常基本的概念,但是也非常容易让人误解,看了很多文章,自我感觉真正将这个问题讲的很透彻的文章还没有看见,所以自告奋勇来尝试一下.如果左值右值的概念不是非常清楚的话,它们迟早会像拦路虎一样跳出来,让你烦心不已,就像玩电脑游戏的时候每隔一段时间总有那么几个地雷考验你的耐性,如果一次把所有地雷扫尽就好了.:) 左值(lvalue)和右值(

[C/C++不常见语法特性]_[初级]_[左值-右值-lvalue-rvalue]

参考:1. http://en.cppreference.com/w/cpp/language/value_category   << Value categories >> 2. https://msdn.microsoft.com/en-us/library/dd293668.aspx   << Rvalue Reference Declarator: && >>3. https://msdn.microsoft.com/en-us/li

左值右值

左值就是可以放在赋值号左边赋值的,必须要在内存有实体 右值就是可以放在赋值号右边取出值赋给其他变量的值,可以在内存,也可以在CPU 引用说明为对象建立引用名,即别名 引用在定义初始化时与对象名绑定,程序中不能对引用重定义 一个对象的别名,从使用方式和效果上,与使用对象名一致 定义形式:类型&引用名=对象名; //引用可以改变指针的指向 //引用可以改变指针指向的值 1 #include <iostream> 2 using namespace std; 3 4 void main()

C++学习之路: 左值&amp;右值 的讨论

本章我们讨论一下左值和右值, 剔除我们在学习C语言时养成一些错误常识. 先上代码 1 #include <iostream> 2 #include <string> 3 using namespace std; 4 5 6 //在c++98中,变量分为左值和右值,左值指的是可以取地址的变量,右值指的是非左值.二者的根本区别在于能否获取内存地址,能否赋值不是区分的依据. 7 8 //根据这个原则 我们尝试给以下2个变量和2个表达式 取地址 9 string one("one