Хабр Курсы для всех
РЕКЛАМА
Практикум, Хекслет, SkyPro, авторские курсы — собрали всех и попросили скидки. Осталось выбрать!
templateT move_if_rr( T&& val )
{
return std::move(val);
}
templateconst T& move_if_rr( const T& val )
{
return val;
}template< class T >
void f( T &&rr )
{
// это следует читать как
// "сделать std::move для some_arg, если rr имеет move семантику,
// иначе просто передать some_arg"
std::move_if_rr< T >( some_arg );
}
Container< A > a;
// вызывается Container<A>::Container<A><Container<A> >(Container<A> &&)
Container< A > b( std::move( a ) );
// вызывается Container<A>::Container<A><Container<A> &>(Container<A> & rr)
Container< A > c( a );
template<typename T> struct helper
{
template<typename U> struct result
{
typedef U&& type;
};
template<typename U> static U&& get( U& u )
{
return static_cast<U&&>(u);
}
};
template<typename T> struct helper<T&>
{
template<typename U> struct result
{
typedef U const& type;
};
template<typename U> static U const& get( U const& u )
{
return u;
}
};
template<typename T, typename U>
typename helper<T>::template result<U>::type move_if_rr( U& v )
{
return helper<T>::get( v );
}template<typename T, typename U> struct helper
{
typedef U&& result;
static U&& get( U& u )
{
return static_cast<U&&>( u );
}
};
template<typename T, typename U> struct helper<T&, U>
{
typedef U const& result;
static U const& get( U const& u )
{
return u;
}
};
template<typename T, typename U>
typename helper<T,U>::result move_if_rr( U& u )
{
return helper<T,U>::get( u );
}
Container c0;
const Container& get_container() {
return c0;
}
Container c1(get_container());
Будет вызван implicit copy constructor. template< class T > Container( T&& );
template<typename T, typename U> struct helper
{
typedef U&& result;
static U&& get( U& u ) { return static_cast<U&&>( u ); }
};
template<typename T, typename U> struct helper<T&, U>
{
typedef U& result;
static U& get( U& u ) { return u;}
};
template<typename T, typename U> typename helper<T,U>::result move_if_rr( U& u )
{
return helper<T,U>::get( u );
}
template< class T >Вызовем ее так:
void Fwd( T &&rr )
{
g( std::forward< T >( rr ) );
}
const Dummy o;В данном случае T == «const Dummy», при этом g будет вызвана с «const Dummy &&», однако «const T &&» — это нифига не rvalue-ссылка на Dummy (мы не можем ничего «переместить» из константного объекта). Т.е. «move_if_rr{ const Dummy }( arg )» не должна перемещать arg. Этого можно добиться либо отказом от rvalue-ссылки (как у меня), либо добавлением модификатора const к типу arg перед оборачиванием его в rvalue ссылку. Семантически это одно и то же, если только у вас нету специализации «g» именно для «const Dummy &&», что само по себе несколько странно. Выбор в пользу отказа от rvalue ссылки сделан исходя из названия функции:
Fwd( std::move( o ) );
template<typename T, typename U> struct helper<T const, U> : helper<T&, U> {};
template<typename T, typename U> struct helper
{
typedef U&& result;
static U&& get( U& u ) { return static_cast<U&&>( u ); }
};
template<typename T, typename U> struct helper<T&, U>
{
typedef U& result;
static U& get( U& u ) { return u;}
};
template<typename T, typename U> struct helper<T const, U> : helper<T&, U> {};
template<typename T, typename U> typename helper<T,U>::result move_if_rr( U& u )
{
return helper<T,U>::get( u );
}
template<typename T, typename U> struct helper
{ typedef U&& result; };
template<typename T, typename U> struct helper<T&, U>
{ typedef U& result; };
template<typename T, typename U> struct helper<T const, U>
: helper<T&, U> {};
template<typename T,typename U> typename helper<T,U>::result move_if_rr(U&u)
{
return static_cast<helper<T,U>::result>( u );
}
#define RET_TYPE \
typename std::conditional< \
std::is_rvalue_reference<E>::value \
, typename std::remove_reference<I>::type&& \
, I&& \
>::type
template <typename E, typename I>
RET_TYPE move_if_rr(I&& i)
{
return static_cast<RET_TYPE>(i);
}
#define RET_TYPE \
typename std::conditional< \
C \
, typename std::remove_reference<I>::type&& \
, I&& \
>::type
template <bool C, typename I>
RET_TYPE move_if(I&& i)
{
return static_cast<RET_TYPE>(i);
}
move_if<std::is_rvalue_reference<A>::value>(b);
member = move_if_rr< T >( rr.Get() );наmember = move_if_rr< T&& >( rr.Get() );, что как раз укладывается в моем представлении. Ведь rr имеет тип T&&, а не T.typedef A T1;По сути у вас 2 проблемы, одна из которых спорная:
typedef A &T2;
typedef const A &T3;
typedef const A T4;
// move_if_rr< FWD >( Arg ) = Res
//
// Я буду писать так:
// ( FWD, Arg ) ? Res
// Следующие выражения не будут верны:
// 1. ( T2 &&, const B && ) == const B & (Ваш код даст const B &&)
// 2. ( T2 &&, B && ) == B & (Ваш код даст B &&)
// 3. ( T3 &&, const B && ) == const B & (Ваш код даст const B &&)
// 4. ( T3 &&, B && ) == B & (Ваш код даст B &&)
// 5. ( T4 &&, const B && ) == const B & (Ваш код даст const B &&)
// 6. ( T4 &&, const B & ) == const B & (Ваш код даст const B &&)
// 7. ( T4 &&, B && ) == B & (Ваш код даст B &&)
// 8. ( T4 &&, B & ) == B & (Ваш код даст B &&)
А понимаете ли Вы move семантику?