简体   繁体   English

const方法中decltype的结果

[英]Result of decltype in const methods

The C++11 decltype returns the type of the expression given to it (mostly). C ++ 11 decltype返回给定的表达式的类型(主要是)。 But this can differ from the type of the expression as it is actually accessible: 但这可能与表达式的类型不同,因为它实际上是可访问的:

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

In the example, the Ref struct is just used to cause a compile error if T does not match the actual constructor argument. 在该示例中,如果T与实际构造函数参数不匹配,则Ref结构仅用于导致编译错误。 The Problem::doit_c() method is where decltype(n) returns a non-const result, even though n is const in this context. Problem::doit_c()方法是decltype(n)返回非const结果的地方,即使n在此上下文中是const。

If one switches from the standard decltype to the GNU extension typeof , this seems to take the const-ness of the method into account. 如果从标准decltype切换到GNU扩展typeof ,这似乎考虑了方法的常量。

Now my question: Is there a C++11 / C++14 / C++17 compliant alternative to decltype() / typeof() that behaves "correctly" (as in: no compile error above) for expressions like the declaration in the const-method above? 现在我的问题:是否有符合C ++ 11 / C ++ 14 / C ++ 17的替代decltype() / typeof()行为“正确”(如:上面没有编译错误)对于像声明这样的表达式在上面的const方法?

Edited: 编辑:

  • Simplified the first sentence to remove some errors and stop distracting from the point of the question (thanks, @skypjack) 简化第一句删除一些错误并停止分散注意力的问题(谢谢,@ skypjack)

  • Simplified the use use of macros in the example code (thanks, @Richard Critten) 简化了示例代码中宏的使用(谢谢,@ Richard Critten)

decltype is a feature that kinda sits at two chairs at once. decltype是一种有时同时坐在两把椅子上的功能。 Firstly, as the name suggests, it can give you the exact declared type of an entity, ignoring the context in which it is used. 首先,顾名思义,它可以为您提供实体的确切声明类型,忽略使用它的上下文。 Secondly, it can treat its argument as an expression, whose exact type depends on the context and its value category. 其次,它可以将其参数视为一个表达式,其确切类型取决于上下文及其值类别。

decltype applied directly to a "naked" (unparenthesized) class member access is a special case, in which decltype acts in accordance with its first role. decltype直接应用于“裸”(unsarenthesized)类成员访问是一种特殊情况,其中decltype根据其第一个角色起作用。 It will not treat n as an expression. 它不会将n视为表达式。 Instead it will produce the type of that class member, ignoring the context. 相反,它将生成该类成员的类型,忽略上下文。

If you want it to treat n as an expression, you have to parenthesize it 如果您希望将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
  }
};

You can find out the effective cv-qualified type of n using a temporary reference: 您可以使用临时引用找出有效的cv限定类型的n

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

But it's simpler and clearer to parenthesize, as shown in AnT's answer . 但是如AnT的回答所示,括号内容更简单明了

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM