如何正确使用std :: reference_wrapper

时间:2013-08-08 13:35:38

标签: c++ c++11 stl c++-standard-library

我想了解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 个答案:

答案 0 :(得分:37)

std::reference_wrapper<T>实现了一个隐式转换运算符T&

operator T& () const noexcept;

和更明确的吸气剂:

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.

但是,有时不一定需要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);替换。 但是,对于模板化运算符(例如ostream::operator <<()),我认为你无法明确表示类型。