const方法中的decltype结果

时间:2017-07-03 14:08:42

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

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在此上下文中是常量。

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

现在我的问题:是否存在符合C ++ 11 / C ++ 14 / C ++ 17的替代decltype() / typeof()的行为&#34;正确&#34;对于像上面const方法中的声明这样的表达式,如上所述:上面没有编译错误?

编辑:

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

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

2 个答案:

答案 0 :(得分:6)

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
  }
};

答案 1 :(得分:1)

您可以使用临时引用找出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所示,括号内容更简单明了。