Movatterモバイル変換


[0]ホーム

URL:


cppreference.com
Namespaces
Variants
    Actions

      std::forward_like

      From cppreference.com
      <cpp‎ |utility
       
       
      Utilities library
       
      Defined in header<utility>
      template<class T,class U>
      constexprauto&& forward_like( U&& x)noexcept;
      (since C++23)

      Returns a reference tox which has similar properties toT&&.

      The return type is determined as below:

      1. Ifstd::remove_reference_t<T> is a const-qualified type, then the referenced type of the return type isconststd::remove_reference_t<U>. Otherwise, the referenced type isstd::remove_reference_t<U>.
      2. IfT&& is an lvalue reference type, then the return type is also an lvalue reference type. Otherwise, the return type is an rvalue reference type.

      IfT is not areferenceable type, the program is ill-formed.

      Contents

      [edit]Parameters

      x - a value needs to be forwarded like typeT

      [edit]Return value

      A reference tox of the type determined as above.

      [edit]Notes

      Likestd::forward,std::move, andstd::as_const,std::forward_like is a type cast that only influences thevalue category of an expression, or potentially adds const-qualification.

      Whenm is an actual member and thuso.m a valid expression, this is usually spelled asstd::forward<decltype(o)>(o).m in C++20 code.

      This leads to three possible models, calledmerge,tuple, andlanguage.

      • merge: merge theconst qualifiers, and adopt the value category of theOwner.
      • tuple: whatstd::get<0>(Owner) does, assumingOwner is astd::tuple<Member>.
      • language: whatstd::forward<decltype(Owner)>(o).m does.

      The main scenario thatstd::forward_like caters to is adapting “far” objects. Neither thetuple nor thelanguage scenarios do the right thing for that main use-case, so themerge model is used forstd::forward_like.

      Feature-test macroValueStdFeature
      __cpp_lib_forward_like202207L(C++23)std::forward_like

      [edit]Possible implementation

      template<class T,class U>constexprauto&& forward_like(U&& x)noexcept{constexprbool is_adding_const=std::is_const_v<std::remove_reference_t<T>>;ifconstexpr(std::is_lvalue_reference_v<T&&>){ifconstexpr(is_adding_const)returnstd::as_const(x);elsereturnstatic_cast<U&>(x);}else{ifconstexpr(is_adding_const)return std::move(std::as_const(x));elsereturn std::move(x);}}

      [edit]Example

      Run this code
      #include <cstddef>#include <iostream>#include <memory>#include <optional>#include <type_traits>#include <utility>#include <vector> struct TypeTeller{void operator()(thisauto&& self){using SelfType= decltype(self);using UnrefSelfType=std::remove_reference_t<SelfType>;ifconstexpr(std::is_lvalue_reference_v<SelfType>){ifconstexpr(std::is_const_v<UnrefSelfType>)std::cout<<"const lvalue\n";elsestd::cout<<"mutable lvalue\n";}else{ifconstexpr(std::is_const_v<UnrefSelfType>)std::cout<<"const rvalue\n";elsestd::cout<<"mutable rvalue\n";}}}; struct FarStates{std::unique_ptr<TypeTeller> ptr;std::optional<TypeTeller> opt;std::vector<TypeTeller> container; auto&& from_opt(thisauto&& self){return std::forward_like<decltype(self)>(self.opt.value());// It is OK to use std::forward<decltype(self)>(self).opt.value(),// because std::optional provides suitable accessors.} auto&& operator[](thisauto&& self,std::size_t i){return std::forward_like<decltype(self)>(self.container.at(i));// It is not so good to use std::forward<decltype(self)>(self)[i], because// containers do not provide rvalue subscript access, although they could.} auto&& from_ptr(thisauto&& self){if(!self.ptr)throwstd::bad_optional_access{};return std::forward_like<decltype(self)>(*self.ptr);// It is not good to use *std::forward<decltype(self)>(self).ptr, because// std::unique_ptr<TypeTeller> always dereferences to a non-const lvalue.}}; int main(){    FarStates my_state{        .ptr{std::make_unique<TypeTeller>()},        .opt{std::in_place, TypeTeller{}},        .container{std::vector<TypeTeller>(1)},};     my_state.from_ptr()();    my_state.from_opt()();    my_state[0](); std::cout<<'\n'; std::as_const(my_state).from_ptr()();std::as_const(my_state).from_opt()();std::as_const(my_state)[0](); std::cout<<'\n';     std::move(my_state).from_ptr()();    std::move(my_state).from_opt()();    std::move(my_state)[0](); std::cout<<'\n';     std::move(std::as_const(my_state)).from_ptr()();    std::move(std::as_const(my_state)).from_opt()();    std::move(std::as_const(my_state))[0](); std::cout<<'\n';}

      Output:

      mutable lvaluemutable lvaluemutable lvalue const lvalueconst lvalueconst lvalue mutable rvaluemutable rvaluemutable rvalue const rvalueconst rvalueconst rvalue

      [edit]See also

      (C++11)
      converts the argument to an xvalue
      (function template)[edit]
      (C++11)
      forwards a function argument and use the type template argument to preserve its value category
      (function template)[edit]
      (C++17)
      obtains a reference toconst to its argument
      (function template)[edit]
      Retrieved from "https://en.cppreference.com/mwiki/index.php?title=cpp/utility/forward_like&oldid=173328"

      [8]ページ先頭

      ©2009-2025 Movatter.jp