【问题标题】:Type of member variables in a const member functionconst 成员函数中的成员变量类型
【发布时间】:2020-09-29 22:38:27
【问题描述】:

当我有一个标记为 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,即 value 将是 const int。但是,当使用编译器错误推断类型时,我得到了我不期望的类型。

void const_type_test::test() const 的错误输出:聚合 type_printer&lt;int&gt; _ 类型不完整,无法定义,type_printer&lt;decltype(value)&gt; _;

所以我看到类型被推断为 int。我认为这将是 const int 因为您无法更改该值。我使用 decltype 错误吗?还是我的理解有漏洞。

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

示例 3 显示以下错误:错误:聚合 type_printer&lt;const int&amp;&gt; _ 类型不完整,无法定义 type_printer&lt;decltype(x)&gt; _。我期望它被推断为 const 引用。

示例 4:还推导出一个 type_printer&lt;const int&amp;&gt;,我认为它是一个指针。

渴望获得一些参考标准,以找出我的知识漏洞在哪里。我也想知道在使用decltype 时是否有一些奇怪的类型推导规则让我感到困惑。

【问题讨论】:

    标签: c++ constants type-deduction


    【解决方案1】:

    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)> _;
    

    带括号:

     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.com/w/cpp/language/decltype

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

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

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

    【讨论】:

    • 此特殊规则也适用于常规变量。
    【解决方案2】:

    确保您使用的是正确的类型。有些类型的范围比其他类型低

    【讨论】:

      最近更新 更多