Why use a perfectly forwarded value (a functor)?

前端 未结 2 1514
盖世英雄少女心
盖世英雄少女心 2020-12-13 00:28

C++11 (and C++14) introduces additional language constructs and improvements that target generic programming. These include features such as;

  • R-value reference
2条回答
  •  轻奢々
    轻奢々 (楼主)
    2020-12-13 01:08

    Here is a practical example.

    struct concat {
      std::vector state;
      std::vector const& operator()(int x)&{
        state.push_back(x);
        return state;
      }
      std::vector operator()(int x)&&{
        state.push_back(x);
        return std::move(state);
      }
      std::vector const& operator()()&{ return state; }
      std::vector operator()()&&{ return std::move(state); }
    };
    

    This function object takes an x, and concatenates it to an internal std::vector. It then returns that std::vector.

    If evaluated in an rvalue context it moves to a temporary, otherwise it returns a const& to the internal vector.

    Now we call apply:

    auto result = apply( concat{}, std::make_tuple(2) );
    

    because we carefully forwarded our function object, only 1 std::vector buffer is allocated. It is simply moved out to result.

    Without the careful forwarding, we end up creating an internal std::vector, and we copy it to result, then discard the internal std::vector.

    Because the operator()&& knows that the function object should be treated as a rvalue about to be destroyed, it can rip the guts out of the function object while doing its operation. The operator()& cannot do this.

    Careful use of perfect forwarding of function objects enables this optimization.

    Note, however, that there is very little use of this technique "in the wild" at this point. Rvalue qualified overloading is obscure, and doing so to operator() moreso.

    I could easily see future versions of C++ automatically using the rvalue state of a lambda to implicitly move its captured-by-value data in certain contexts, however.

提交回复
热议问题