Как правильно использовать std:: reference_wrappers
Я пытаюсь понять std::reference_wrapper
.
Следующий код показывает, что ссылочная оболочка не ведет себя точно так же, как ссылка.
#include <iostream>
#include <vector>
#include <functional>
int main()
{
std::vector<int> numbers = {1, 3, 0, -8, 5, 3, 1};
auto referenceWrapper = std::ref(numbers);
std::vector<int>& reference = numbers;
std::cout << reference[3] << std::endl;
std::cout << referenceWrapper.get()[3] << std::endl;
// I need to use get ^
// otherwise does not compile.
return 0;
}
Если я правильно понимаю, неявное преобразование не применяется к вызовам функций-членов. Является ли это неотъемлемым ограничением? Нужно ли часто использовать std::reference_wrapper::get
?
Другим случаем является следующее:
#include <iostream>
#include <functional>
int main()
{
int a = 3;
int b = 4;
auto refa = std::ref(a);
auto refb = std::ref(b);
if (refa < refb)
std::cout << "success" << std::endl;
return 0;
}
Это отлично работает, но когда я добавляю это выше определения main
:
template <typename T>
bool operator < (T left, T right)
{
return left.someMember();
}
Компилятор пытается создать экземпляр шаблона и забыть о неявном преобразовании и встроенном операторе.
Является ли это поведение присущим или я неправильно понимаю что-то важное в std::reference_wrapper
?
Ответы
Ответ 1
Класс std::reference_wrapper<T>
реализует оператор неявного преобразования в T&
:
operator T& () const noexcept;
и более явный getter:
T& get() const noexcept;
Неявный оператор вызывается, когда требуется T
(или T&
). Например,
void f(some_type x);
// ...
std::reference_wrapper<some_type> x;
some_type y = x; // the implicit operator is called
f(x); // the implicit operator is called and the result goes to f.
Однако иногда a T
не обязательно ожидается, и в этом случае вы должны использовать get
. Это происходит, главным образом, в контексте автоматического вычитания типов. Например,
template <typename U>
g(U x);
// ...
std::reference_wrapper<some_type> x;
auto y = x; // the type of y is std::reference_wrapper<some_type>
g(x); // U = std::reference_wrapper<some_type>
Чтобы получить some_type
вместо std::reference_wrapper<some_type>
выше, вы должны сделать
auto y = x.get(); // the type of y is some_type
g(x.get()); // U = some_type
Альтернативно последняя строка выше может быть заменена на g<some_type>(x);
.
Тем не менее, для templatized операторов (например, ostream::operator <<()
) я считаю, что вы не можете указать тип.