Интересно, как можно сделать следующее:
void f(string &&s) {
std::string i(move(s));
/* other stuff */
}
int main() {
std::string s;
bind(f, s)(); // Error.
bind(f, move(s))(); // Error.
bind(f, ref(s))(); // Error.
}
Как передать ссылку rvalue и сохранить ее как ссылку rvalue (возможно, завернутую) в оболочку вызова? Я знаю, что могу вручную написать класс типа std::reference_wrapper<>
, который имеет функцию преобразования для T&&
, но я бы предпочел избежать этого и использовать стандартную технологию.
Я реализовал его, как рекомендует AProgrammer:
template<typename T> struct adv {
T t;
explicit adv(T &&t):t(forward<T>(t)) {}
template<typename ...U> T &&operator()(U &&...) {
return forward<T>(t);
}
};
template<typename T> adv<T> make_adv(T &&t) {
return adv<T>{forward<T>(t)};
}
namespace std {
template<typename T>
struct is_bind_expression< adv<T> > : std::true_type {};
}
Теперь я могу сказать
void f(string &&s) {
std::string i(move(s));
/* other stuff */
}
int main() {
std::string s;
bind(f, make_adv(move(s)))(); // Works!
}
Если мы передадим значение lvalue в make_adv
, он пересылает его как lvalue, ссылаясь на входной аргумент, поэтому в этом случае он может быть заменен на std::ref
.