常量成员函数中成员变量的类型。

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

当我把一个成员函数标记为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;
}

我的理解是,当你在const方法中时,该方法实际上是一些名字被篡改的名字,然后他们的参数类型是类名const* const。我一直以为在const方法的范围内,成员变量实际上是const,即值将是const int。然而,当使用编译器错误来推断类型时,我得到了我不期望的类型。

错误输出为 void const_type_test::test() const:合计 type_printer<int> _ 具有不完整的类型,无法定义。type_printer<decltype(value)> _;

所以我看到类型被推断为int。我以为会是const int,因为你不能改变值。我是不是用错了decltype?还是我的理解有漏洞。

我想问的原因是,在 test2 编译器抱怨:绑定引用类型为 int&const int 抛弃限定词。这正是我所期望的。可以将一个const引用绑定到非const引用。

例3显示了以下错误:错误:aggregation type_printer<const int&> _ 类型不全,无法定义 type_printer<decltype(x)> _. 这就是我所期望的,它已经被推导为一个const引用。

例4: 也推导出一个 type_printer<const int&> 我想这应该是一个指针。

很想找一些标准的参考,看看我知识的漏洞在哪里。我还想知道在使用 decltype 困扰着我。

c++ const type-deduction
1个回答
6
投票

decltype 对类成员有特殊的规则。它返回成员的实际类型。如果你想用 decltype 来考虑上下文(在一个const函数内),那么你可以将表达式包装在括号内。

无括号。

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

With Paranthesis:

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

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

参考。

https:/en.cppreference.comwcpplanguagedecltype

如果参数是一个未括号的id表达式或 一个未括号的类成员访问表达式。,那么decltype就会产生这个表达式所命名的实体的类型。如果没有这样的实体,或者如果参数命名了一组重载函数,那么程序就是不正规的。

https:/docs.microsoft.comen-uscppcppdecltype-cpp?view=vs-2019。

如果表达式参数是一个标识符或 课堂成员访问decltype(expression)是由expression命名的实体的类型,如果没有这样的实体或者expression参数命名了一组重载函数,编译器就会产生错误信息。如果没有这样的实体,或者表达式参数命名了一组重载函数,编译器就会产生一个错误信息。

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