为什么 decltype(member) 不是 const,而 decltype((member)) 用于 const 对象以及它如何影响函数调用

问题描述 投票:0回答:1

我不明白以下代码片段的行为,它是从实际代码派生的

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)
,它将是模板参数推导的“输入”。
在大多数情况下,差异似乎是不可见的,但在处理常量时,它变得至关重要,如提供的代码片段中所示。

我遗漏了什么细节?当将表达式(可能是单个变量)传递给函数时,函数“看到”的表达式的类型是什么(这将影响模板参数推导,但也可能影响重载决策)?

这显然是一个基本问题,但到目前为止我还没有想到这些微妙之处。上面的链接帖子是关于它的,但我仍然错过了函数调用时实际发生的事情。

c++ constants language-lawyer member template-argument-deduction
1个回答
0
投票

我错过了什么细节?当将表达式(可能是单个变量)传递给函数时,函数“看到”的表达式的类型是什么(这将影响模板参数推导,但也可能会重载解决)? 我仍然不知道函数调用时实际发生的情况。

Getter
val
上调用,通过引用传递,但
T
被推导为
const int
,就好像参数是对 const lvalue 的引用一样(
const int &
).

您错过了当

val
作为函数调用中的函数参数传递时
Getter(val)
是一个具有值类别 lvalue 且类型为
const int
的表达式(不是
const int&
因为 表达式永远没有引用输入 c++)。

© www.soinside.com 2019 - 2024. All rights reserved.