• c++11 perfect forwarding


    完美转发是c++11 引入右值引用之后,在template 中的延伸. 顾名思义,完美转发是将参数不改变属性的条件下,转发给下一个函数. 因为普通函数的参数一旦具名,始终都是lvalue. 如果把rvalue转发到下一个函数上的参数中,还是rvalue.这就是完美转发的目的。

    #include<iostream>
    using namespace std;
     
    struct X {};
    void inner(const X&) {cout << "inner(const X&)" << endl;}
    void inner(X&&) {cout << "inner(X&&)" << endl;}
    template<typename T>
    void outer(T&& t) {inner(forward<T>(t));}
     
    int main()
    {
    	X a;
    	outer(a);
    	outer(X());
    	inner(forward<X>(X()));
    }
    //inner(const X&)
    //inner(X&&)
    //inner(X&&)

    那么如何支持完美转发呢?第一反应就是用通用引用;假设如此实现:

    template<class T>
    T&& forwarding(T&& t){
      return static_cast<T&&>(param);
    }
    

     传入左值的时候是forward(x), 传入右值是forward(X()),看起来符合要求。但是这里用错了完美转发的具体场景,也就是通常我们用完美转发是什么形式呢?如果不使用完美转发,那么在template function会出现什么情况?

    template <typename T>
    void relay(T&& t) {
        cout << "in relay" << endl;
        func(t);
    }
    

     relay(temp());传入的是右值,但是转发的时候t被认为左值. 不符合完美转发语义

    template<typename T>
    void foo(T&& fparam)
    {
        std::forward<T>(fparam);
    }
    

      

     以上是完美转发的场景,完美转发配套通用引用,才是它的应用场景, 因为param已经具名,所以是lvalue,刚才的简单实现,显然不符合。

    template <typename T>
    T&& forward(typename remove_reference<T>::type& param)
    {
        return static_cast<T&&>(param);
    }
    

     以上实现,才是完美转发的主要实现,为什么是主要实现,因为它是最多场景的实现。我们分析一下foo(A());T被推导为A,fparam是lvalue,param是A&。因此匹配

    但是如果我们翻C++ 完美转发的实现:貌似还有另外一个实现:
    template <class T> T&& forward(typename remove_reference<T>::type&& t) noexcept;
    这里应对什么场景呢?直接调用forward<A>(A())的场景。 注意这里typename remove_reference<T>::type&&不再是通用引用,而是右值引用。之前的左值引用,不能接右值,所以需要重定义一个函数.

    以上就实现了完美转发的所有内容.完美转发的根基是引用折叠和通用引用.
       其他:
    template< class T > struct remove_reference      {typedef T type;};
    template< class T > struct remove_reference<T&>  {typedef T type;};
    template< class T > struct remove_reference<T&&> {typedef T type;}; 
    

      

  • 相关阅读:
    找回Android studio的帮助文档
    adb shell 命令详解
    Android 获取Activity当前view
    下载网络文件HttpURLConnection.getContentLength()大小为 0
    Android设置屏幕旋转后保存数据
    解决TextView drawableRight左侧图片大小不可控的问题
    Android全屏(包含3种隐藏顶部状态栏及标题栏和一种隐藏Android 4.0平板底部状态栏的方法)
    人生苦短,我用Python(目录)
    爬虫学习目录
    Django-jet自定义菜单
  • 原文地址:https://www.cnblogs.com/kkshaq/p/10445137.html
Copyright © 2020-2023  润新知