std::ref 隐式转换为引用混淆

std::ref implicit conversion to reference confusion

我知道 std::ref(object) 创建了一个 std::reference_wrapper(object),并且 std::reference_wrapper 有一个不明确的类型转换运算符成员函数

operator T&() const

而且我知道这会影响我在模板参数推导发挥作用时使用它的方式: 所以在下面的 Print 中,如果我用 std::ref("hello")

调用它,则参数的类型 T 被推断为 std::reference_wrapper
template <class T>
void Print(T t)
{
    std::cout << t << std::end;
}

为什么这行不编译?

std::string s = "hello";
std::cout << std::reference_wrapper<std::string>(s) << std::endl;

实例化的特化应该有一个

operator std::string&() const

类型转换函数,为什么我不能使用这样的引用包装器?

您尝试使用的 operator<< 重载具有以下形式(来自 cppreference.com):

template <class CharT, class Traits, class Allocator>

std::basic_ostream<CharT, Traits>&
    operator<<(std::basic_ostream<CharT, Traits>& os,
               const std::basic_string<CharT, Traits, Allocator>& str);

第二个函数参数包含模板参数,不是非推导上下文。因此它必须推导出模板参数。模板参数推导不考虑隐式转换,并且由于 std::reference_wrapper 不是 std::basic_string,推导将失败。 std::reference_wrapper 是否可以转换为 std::string(或对一个的引用)并不重要。

澄清一下,std::stringstd::basic_string 的专业化 std::basic_string<char, std::char_traits<char>, std::allocator<char>> 的别名。 std::basic_string 可以专门用于任何字符类型,例如 wchar_t(别名为 std::wstring)。其他专业根本不经常使用。