Чтобы заставить этот код с ссылочными квалификаторами С++ 11 работать должным образом, я должен ввести std::move(*this)
, который звучит неправильно.
#include<iostream>
struct A{
void gun() const&{std::cout << "gun const&" << std::endl;}
void gun() &&{std::cout << "gun&&" << std::endl;}
void fun() const&{gun();}
void fun() &&{std::move(*this).gun();} // <-- is this correct? or is there a better option
};
int main(){
A a; a.fun(); // prints gun const&
A().fun(); // prints gun&&
}
Что-то не так в этом. Нужен ли std::move
? Это рекомендуемое использование? На данный момент, если я не использую его, я получаю gun const&
в обоих случаях, что не является ожидаемым результатом.
(Кажется, что *this
является неявным и всегда имеет ссылку на lvalue, что имеет смысл, но тогда единственный способ избежать использования move
)
Протестировано с clang 3.4
и gcc 4.8.3
.
РЕДАКТИРОВАТЬ: Это то, что я понимаю из ответа @hvd:
1) std::move(*this)
является синтаксически и концептуально правильным
2) Однако, если gun
не является частью желаемого интерфейса, нет причин перегружать его версиями lv-ref и rv-ref. И две функции с разными именами могут выполнять одну и ту же работу. В конце концов, ref-определители имеют значение на уровне интерфейса, который обычно является только публичной частью.
struct A{
private:
void gun() const{std::cout << "gun const&" << std::endl;}
void gun_rv(){std::cout << "gun called from fun&&" << std::endl;}
public:
void fun() const&{gun();}
void fun() &&{gun_rv();} // no need for 'std::move(*this)'.
};
Но опять же, если gun
является частью (универсального) интерфейса, тогда std::move(*this)
необходим, но только тогда. Кроме того, даже если gun
не является частью интерфейса, есть преимущества читабельности, заключающиеся в том, что функция gun
не разделяется на две функции с разными именами, и стоимость этого, ну..., std::move(*this)
.
РЕДАКТИРОВАНИЕ 2: в ретроспективе это похоже на случай С++ 98 с перегрузкой const
и no- const
одной и той же функции. В некоторых случаях имеет смысл использовать const_cast
(другую форму приведения), чтобы не повторять код и иметь две функции с одинаковым именем (qaru.site/info/29860/...)