Интересно, как можно сделать следующее
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
.