【问题标题】:Result of decltype in const methodsconst 方法中 decltype 的结果
【发布时间】:2017-07-03 14:08:42
【问题描述】:

C++11 decltype 返回给它的表达式的类型(大部分)。但这可能与表达式的类型不同,因为它实际上是可访问的:

template<typename T>
struct Ref {
    Ref(T&) { }
};

#define GETTYPE decltype
//#define GETTYPE typeof

struct Problem {
    void doit_c() const { Ref<GETTYPE(n)> rn{n}; }
    void doit_nc()      { Ref<GETTYPE(n)> rn{n}; }
    int n;
};

int main() {
    int i;
    const int ci = 0;
    Problem pr;

    // decltype == typeof == int
    Ref<GETTYPE(i)> ri{i};
    pr.doit_nc();

    // decltype == typeof == const int
    Ref<GETTYPE(ci)> rci{ci};
    Ref<GETTYPE(static_cast<const int&>(i))> rcci{static_cast<const int&>(i)};

    // typeof == const int, decltype == int (!)
    pr.doit_c();

    return 0;
}

在示例中,Ref 结构仅用于在 T 与实际构造函数参数不匹配时导致编译错误。 Problem::doit_c() 方法是 decltype(n) 返回非 const 结果的地方,即使 n 在此上下文中是 const。

如果从标准 decltype 切换到 GNU 扩展 typeof,这似乎考虑了该方法的 const-ness。

现在我的问题:对于表达式,是否有符合 C++11 / C++14 / C++17 的替代 decltype() / typeof() 表现“正确”(如:上面没有编译错误)像上面的 const-method 中的声明?

已编辑:

  • 简化了第一句话以消除一些错误并停止分散问题的注意力(感谢@skypjack)

  • 简化了示例代码中宏的使用(感谢@Richard Critten)

【问题讨论】:

  • C++11 decltype 在声明类型时返回给它的表达式的类型。这不准确。 decltype 有很多规则与你的说法或多或少有所不同。
  • 请不要在示例问题中使用宏(除非问题与宏有关)。
  • “即使 n 在这种情况下是 const。” 不,不是。 this 指针指向 const 对象。在 const 对象中声明的成员 int n 仍然是 int,而不是 const int。在我看来,decltype()的判断是正确的,而不是typeof()的判断。
  • 完全没有想到,我猜你可以在*this 上使用is_const,如果那是true,那么add_const 是会员的类型。跨度>
  • "在 const 对象中声明的成员 int n 仍然是 int,而不是 const int。"我同意该类型的成员变量是非常量的。但是Problem::doit_c() 中的左值nconst,编译器抱怨就证明了这一点。

标签: c++ c++11 typeof decltype


【解决方案1】:

decltype 是一个可以同时坐在两把椅子上的功能。首先,顾名思义,它可以为您提供实体的确切声明类型,而忽略使用它的上下文。其次,它可以将其参数视为一个表达式,其确切类型取决于上下文及其值类别。

decltype 直接应用于“裸”(无括号)类成员访问是一种特殊情况,其中decltype 与其第一个角色一致。它不会将n 视为表达式。相反,它将生成该类成员的类型,而忽略上下文。

如果你想让它把n当作一个表达式,你必须给它加上括号

struct Problem {
  void doit_c() const 
  { 
    Ref<decltype(n)> rn1{n}; // `decltype(n)` is `int` -> ERROR
    Ref<decltype((n))> rn2{n}; // `decltype((n))` is `const int &` -> compiles OK
  }
};

【讨论】:

  • 当然!我知道我的回答中遗漏了一些东西(我的脑海里有关于将值从后到前括起来的规则)。
  • decltype((n))const 因为 doit_c()const?
【解决方案2】:

您可以使用临时引用找出n 的有效 cv 限定类型:

void doit_c() const { auto& x = n; Ref<GETTYPE(x)> rn{n}; }
void doit_nc()      { auto& x = n; Ref<GETTYPE(x)> rn{n}; }

但括号更简单明了,如AnT's answer所示。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-02-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多