const成员函数中成员变量的类型

Bla*_*son 12 c++ constants type-deduction

当我有一个标记为 const 的成员函数并检查成员变量的类型时,我得到了一些我不期望的结果。

#include <iostream>
#include <string>

template<typename T>
struct type_printer;

class const_type_test {
public:
    void test() const {
        type_printer<decltype(value)> _;
    }
    int& test2() const {
        return value;
    }
    void test3() const {
        auto& x = value;
        type_printer<decltype(x)> _;
    }
    void test4() const {
        auto* x = &value;
        type_printer<decltype(*x)> _;
    }
private:
    int value;
};

int main(int argc, char** argv) 
{
    const const_type_test x;

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

我的理解是,当您使用 const 方法时,该方法实际上是一些名称混淆的名称,然后它们的参数类型是 classname const* const。我一直认为在 const 方法范围内,成员变量实际上是 const,即值将是 const int。但是,当使用编译器错误来推断类型时,我得到了我不期望的类型。

错误输出void const_type_test::test() const:aggregatetype_printer<int> _类型不完整,无法定义,type_printer<decltype(value)> _;

所以我看到类型被推断为 int。我认为它是 const int ,因为您无法更改该值。我使用 decltype 错了吗?或者我的理解有问题。

我猜想询问的原因是test2编译器抱怨:将类型的引用绑定int&const int丢弃限定符。这正是我所期望的。可以将 const 引用绑定到非 const 引用。

示例 3 显示了以下错误:错误:聚合的type_printer<const int&> _类型不完整,无法定义type_printer<decltype(x)> _。这是我所期望的,它被推导出为常量引用。

示例 4:还推导出 a type_printer<const int&>,我认为它是一个指针。

渴望获得对标准的一些参考,以找出我知识中的漏洞。我还想知道在使用时是否有一些奇怪的类型推导规则decltype让我绊倒。

Sha*_*k V 7

decltype对班级成员有特殊规定。它返回成员的实际类型。如果要decltype考虑上下文(在 const 函数内),则可以将表达式括在括号内。

不带括号:

 void test() const {
        type_printer<decltype(value)> _;
    }
Run Code Online (Sandbox Code Playgroud)
c.cpp:10:39: error: implicit instantiation of undefined template 'type_printer<int>'
        type_printer<decltype(value)> _;
Run Code Online (Sandbox Code Playgroud)

带括号:

 void test() const {
        type_printer<decltype((value))> _;
    }

Run Code Online (Sandbox Code Playgroud)
c.cpp:10:41: error: implicit instantiation of undefined template 'type_printer<const int &>'
        type_printer<decltype((value))> _;
Run Code Online (Sandbox Code Playgroud)

参考:

https://en.cppreference.com/w/cpp/language/decltype

如果参数是无括号的 id-expression 或无括号的类成员访问 expression,则 decltype 产生由此表达式命名的实体的类型。如果没有这样的实体,或者参数命名了一组重载函数,则程序格式错误。

https://docs.microsoft.com/en-us/cpp/cpp/decltype-cpp?view=vs-2019

如果表达式参数是标识符或类成员 access,则 decltype(expression) 是由表达式命名的实体的类型。如果没有这样的实体或表达式参数命名一组重载函数,编译器会产生错误消息。