c++ - 为什么右值引用参数与重载决策中的 const 引用匹配?

标签 c++ c++11 c++17 c++14 rvalue-reference

可能相关的文章:

对于 STL 容器 C , std::begin(C)和类似的访问功能包括 std::data(C) (C++17 起)应该具有与 C::begin() 相同的行为和其他对应的C的方法。但是,由于涉及左值/右值引用和常量的重载解析的详细信息,我观察到一些有趣的行为。

DataType1 int*正如所预料的那样。另外,通过 Boost 的 type_id_with_cvr 确认了这一点。 const vector<int>给出int const*这并不奇怪。

using T = vector<int>;
using DataType1 = decltype(T().data()); // int*
using CT = const T;
using DataType2 = decltype(CT().data()); // int const*

using boost::typeindex::type_id_with_cvr;
cout << type_id_with_cvr<DataType1>() << endl; // prints int*
...

我试过std::data ,它还可以处理数组和非 STL 容器。但它产生 int const* 。同样,std::begin返回一个 const 迭代器,即使 T不是常量。

using T = vector<int>;
using DataType3 = decltype(std::data(T())); // int const* Why ???
using CT = const T;
using DataType4 = decltype(std::data(CT())); // int const*

问题:造成这种差异的原因是什么?我预计C.data()std::data(C)也会以同样的方式表现。

<小时/>

我的一些研究:为了得到int*对于 DataType3 , T必须显式转换为非常量左值引用类型。我试过declval ,并且它正在工作。

using DataType3 = decltype(std::data(std::declval<T&>())); // int*

std::data提供两个重载:

template <class _Cont> constexpr
auto data(_Cont& __c) -> decltype(__c.data()) { return __c.data(); }

// non-const rvalue reference argument matches to this version.
template <class _Cont> constexpr
auto data(const _Cont& __c) -> decltype(__c.data()) { return __c.data(); }

在解决 std::data 的重载函数时, T() ,它是非常量右值引用,与 const T& 匹配。版本而不是 T&版本。

在标准(13.3,over.match)中找到这个特定的重载解析规则并不容易。如果有人能指出这个问题的确切规则,那就更清楚了。

最佳答案

此行为归因于重载解析规则。根据标准 8.5.3/p5.2 引用 [dcl.init.ref],右值引用绑定(bind)到 const 左值引用。在此示例中:

std::data(T())

您向 std::data 提供一个右值。因此,由于重载解析规则,重载:

template <class _Cont> constexpr
auto data(const _Cont& __c) -> decltype(__c.data()) { return __c.data(); }

是一个更好的匹配。因此你得到 const int*

您无法将临时值绑定(bind)到非常量左值引用。

关于c++ - 为什么右值引用参数与重载决策中的 const 引用匹配?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34176219/

相关文章:

c++ - 我可以在std::find_if的并行版本中使用非平凡的可迭代迭代器吗?

c++ - 在 OpenCL 中实现

c++ - 公开对象管理器对象的可接受方式?

c++ - 为什么 std::distance 不适用于 const 和非 const 迭代器的混合?

c++ - 从 Nvidia PTX 访问 bool (C++11) 数组的可移植方法

c++ - 为什么 std::function 作为 std::not2 的参数?

c++ - 为什么我必须对用户定义的文字使用 long double?

c++ - boost::asio::read() 永远阻塞

c++ - 我可以向编译器查询 C++0x "alignas"支持吗?

c++ - 带 auto 的 initializer_list 包含多个表达式