std::vector< std::vector<int> > vecvec;std::vector<int> vec={1,2,3};vecvec.emplace_back( std::move(vec) ); // rvalue reference avoids copy
std::vector< std::vector<int> > vecvec;std::vector<int> vec={1,2,3};vecvec.emplace_back( std::move(vec) ); // rvalue reference avoids copy
std::cref
std::vector< std::vector<int> > vecvec;std::vector<int> vec={1,2,3};vecvec.emplace_back( std::move(vec) ); // rvalue reference avoids copy
std::cref
auto rng=std::vector<int>{1,2,3} | std::ranges::view::filter([](int i){ return 0==i%2; });// DOES NOT COMPILE
rng
would contain dangling reference to std::vector<int>
std::ranges::view::filter
does not compile for rvaluesA foo() { A a=...; ... return a;};
std::move
can make things worseA foo() { A const a=...; ... return a;};
struct A;struct B {private: A m_a;public: A const& getA() const& { return m_a; }};struct C { A getA() const&;};B b;C c;auto const& a=< b or c >.getA();
auto const& a=c.getA();
works thanks to temporary lifetime extensionauto const&
, the right thing happens bool operator<(A const&, A const&);struct C { A getA() const&;} c1, c2;auto const& a=std::min( c1.getA(), c2.getA() );
namespace std { template<typename T> T const& min( T const& lhs, T const& rhs ) { return rhs<lhs ? rhs : lhs; }}
std::min
forgets about rvalue-nessa
danglesbool operator<(A const&, A const&);struct C { A getA() const&;} c1, c2;auto const& a=our::min( c1.getA(), c2.getA() );
namespace our { template<typename Lhs, typename Rhs> decltype(auto) min( Lhs&& lhs, Rhs&& rhs ) { return rhs<lhs ? std::forward<Rhs>(rhs) : std::forward<Lhs>(lhs); }}
our::min
correctly returns A&&
bool operator<(A const&, A const&);struct C { A getA() const&;} c1, c2;auto const& a=our::min( c1.getA(), c2.getA() );
namespace our { template<typename Lhs, typename Rhs> decltype(auto) min( Lhs&& lhs, Rhs&& rhs ) { return rhs<lhs ? std::forward<Rhs>(rhs) : std::forward<Lhs>(lhs); }}
our::min
correctly returns A&&
a
still danglesdecltype(auto) foo() { auto const& a = some_A(); ... do something ... return a;}
some_A()
returns valueauto foo() { auto const& a = some_A(); ... do something ... return a;}
some_A()
returns value, a
is really value, not referenceauto
if constructed from value or rvalue reference, andauto const&
if constructed from lvalue referencetemplate<typename T>struct decay_rvalues;template<typename T>struct decay_rvalues<T&> { using type=T&;};template<typename T>struct decay_rvalues<T&&> { using type=std::decay_t<T>;};#define auto_cref( var, ... ) \ typename decay_rvalues<decltype((__VA_ARGS__))&&>::type var = ( __VA_ARGS__ );
decltype(auto) foo() { auto_cref( a, some_A() ); ... do something with a ... return a; // no parentheses here!}
auto
!Choice: auto_cref
value const
?
template<typename T>struct decay_rvalues<T&&> {using type=std::decay_t<T> const;};
Then auto_cref_return
for NRVO/move optimization
bool operator<(A const&, A const&);struct C { A getA() const&;} c1, c2;auto_cref( a, our::min( c1.getA(), c2.getA() ) );
namespace our { template<typename Lhs, typename Rhs> decltype(auto) min( Lhs&& lhs, Rhs&& rhs ) { return rhs<lhs ? std::forward<Rhs>(rhs) : std::forward<Lhs>(lhs); }}
our::min
correctly returns rvalue referenceauto_cref
correctly turns it into valuecommon_reference_t
std::common_reference_t< A const&, A const& >
isA const&
std::common_reference_t< A const&&, A const&& >
isA const&&
std::common_reference_t< A const&&, A const& >
isA const&
!std::common_reference_t< A const, A const& >
iscommon_reference_t
std::common_reference_t< A const&, A const& >
isA const&
std::common_reference_t< A const&&, A const&& >
isA const&&
std::common_reference_t< A const&&, A const& >
isA const&
!std::common_reference_t< A const, A const& >
isA
!common_reference_t
std::common_reference_t< A const&, A const& >
isA const&
std::common_reference_t< A const&&, A const&& >
isA const&&
std::common_reference_t< A const&&, A const& >
isA const&
!std::common_reference_t< A const, A const& >
isA
!std::common_reference
embraces rvalue amnesiacommon_reference_t
std::common_reference_t< A const&, A const& >
isA const&
std::common_reference_t< A const&&, A const&& >
isA const&&
std::common_reference_t< A const&&, A const& >
isA const&
!std::common_reference_t< A const, A const& >
isA
!std::common_reference
embraces rvalue amnesiaWHAT IS CORRECT?
Lifetime short long Mutablityimmutable const&& <----- const& <- ^ \ ^ | -- | \mutable && & [can scavenge]
Better: Allow binding only if promises get weaker
only lvalues should bind to const&
const&&
Warning: These are Ideas! Has not been Implemented!
Existing code must continue to work
Warning: These are Ideas! Has not been Implemented!
Existing code must continue to work
#new-reference-binding on/off
bind along new rulesauto const& a = ... // old rules apply#new-reference-binding onauto const& a = ... // new rules apply#new-reference-binding offauto const& a = ... // old rules apply
#new-reference-binding on/off
bind along new rulesvoid A(int const& a);#new-reference-binding onvoid B(int const& a);void C(int const&& a);#new-reference-binding offvoid B(int const& a) { // error: declared with different binding behavior ...}A(5); // compilesB(5); // error: cannot bind rvalue to lvalueC(5); // compilesint a=1;C(a); // compiles
common_reference
namespace our { template<typename... Ts> struct common_reference { using oldtype=std::common_reference_t<Ts...>; using type=std::conditional_t< std::is_lvalue_reference<oldtype>::value && std::disjunction<std::is_rvalue_reference<Ts> ...>::value, std::remove_reference_t<oldtype>&&, oldtype >; };}
decltype( false ? R() : L() )
?A const
our::common_reference
allows fearless conditional (ternary) operator#define CONDITIONAL(b, l, r) ( \ b \ ? static_cast< typename our::common_reference<decltype((l)),decltype((r))>::type >(l) \ : static_cast< typename our::common_reference<decltype((l)),decltype((r))>::type >(r) \)
decltype( false ? R() : L() )
?A const
our::common_reference
allows fearless conditional (ternary) operator#define CONDITIONAL(b, l, r) ( \ b \ ? static_cast< typename our::common_reference<decltype((l)),decltype((r))>::type >(l) \ : static_cast< typename our::common_reference<decltype((l)),decltype((r))>::type >(r) \)
decltype( CONDITIONAL( false, R(), L() ) )
?A const&&
Keyboard shortcuts
↑, ←, Pg Up, k | Go to previous slide |
↓, →, Pg Dn, Space, j | Go to next slide |
Home | Go to first slide |
End | Go to last slide |
b / m / f | Toggle blackout / mirrored / fullscreen mode |
c | Clone slideshow |
p | Toggle presenter mode |
t | Restart the presentation timer |
?, h | Toggle this help |
Esc | Back to slideshow |