我不明白以下代码片段的行为,它是从实际代码派生的
mre
:
#include <iostream>
#include <type_traits>
// merely returns its input, which is a reference
// could mutualize code for const and non const member function below
template <typename T>
T& Getter(T& i) {
std::cout << std::boolalpha << "Getter, const int: "
<< std::is_same<T, const int>::value
<< " / int: " << std::is_same<T, int>::value << '\n';
return i;
}
struct S {
int val = -1;
// read/write access to the data for mutable object
int& Get() {
std::cout << std::boolalpha << "non-const Get, val const int: "
<< std::is_same<decltype(val), const int>::value
<< " / int: " << std::is_same<decltype(val), int>::value
<< '\n';
std::cout << std::boolalpha << "const Get, (val) const int&: "
<< std::is_same<decltype((val)), const int&>::value
<< " / int&: " << std::is_same<decltype((val)), int&>::value
<< '\n';
return Getter(val);
}
// read-only access to the data for const object
int const& Get() const {
std::cout << std::boolalpha << "const Get, val int const: "
<< std::is_same<decltype(val), const int>::value
<< " / int: " << std::is_same<decltype(val), int>::value
<< '\n';
std::cout << std::boolalpha << "const Get, (val) int const&: "
<< std::is_same<decltype((val)), const int&>::value
<< " / int&: " << std::is_same<decltype((val)), int&>::value
<< '\n';
return Getter(val);
}
};
int main() {
std::cout << "---------------------\nconst\n";
S const ks;
std::cout << ks.Get() << '\n';
}
输出如下:
---------------------
const
const Get, val const int: false / int: true
const Get, (val) const int&: true / int&: false
Getter, const int: true / int: false
ks
是 const
因此我打电话给 S::Get() const
:好的S::Get() const
decltype(val)
是int
但是decltype((val))
是const int&
:我觉得很奇怪。标准中明确定义了此行为(请参阅人类友好版本,尤其是 2-b))
但我不明白这背后的道理。
Getter
在 val
上调用,通过引用传递,但 T
被推导为 const int
,就好像参数是对 const lvalue (const int &
) 的引用。
我原以为它将是
decltype(val)
,它将是模板参数推导的“输入”。我遗漏了什么细节?当将表达式(可能是单个变量)传递给函数时,函数“看到”的表达式的类型是什么(这将影响模板参数推导,但也可能影响重载决策)?
这显然是一个基本问题,但到目前为止我还没有想到这些微妙之处。上面的链接帖子是关于它的,但我仍然错过了函数调用时实际发生的事情。
我错过了什么细节?当将表达式(可能是单个变量)传递给函数时,函数“看到”的表达式的类型是什么(这将影响模板参数推导,但也可能会重载解决)? 我仍然不知道函数调用时实际发生的情况。
在Getter
上调用,通过引用传递,但val
被推导为T
,就好像参数是对 const lvalue 的引用一样(const int
).const int &
您错过了当
val
作为函数调用中的函数参数传递时 Getter(val)
是一个具有值类别 lvalue 且类型为 const int
的表达式(不是 const int&
因为 表达式永远没有引用输入 c++)。