使用 decltype 将其强制转换为 const

2022-01-24 00:00:00 constants c++ c++11 decltype

我正在尝试解决一个问题,其中 decltype 将大大简化事情,但我在 *this<上使用 decltype 时遇到了问题/code> 并添加 const 限定符.下面的示例代码演示了这个问题.

I'm attempting to solve a problem in which decltype will greatly simplify things, but I'm running into an issue using decltype on *this and adding a const qualifier. The sample code below demonstrates the problem.

#include <iostream>

struct Foo
{
  void bar()
  {
    static_cast<const decltype(*this)&>(*this).bar();
  }

  void bar() const
  {
    std::cout << "bar" << std::endl;
  }
};

int main(int argc, char* argv[])
{
  Foo f;
  f.bar(); // calls non-const method
  return 0;
}

代码在 MSVC2010 中编译,但会递归执行,直到发生堆栈溢出.

The code compiles in MSVC2010, but execution recurses until a stack overflow occurs.

Ideone 报告编译器错误

prog.cpp: In member function 'void Foo::bar()':
prog.cpp:7:38: error: 'const' qualifiers cannot be applied to 'Foo&'

如果我换行

static_cast<const decltype(*this)&>(*this).bar();

static_cast<const Foo&>(*this).bar();

它按预期工作.

我是否误用或误解了 decltype?

Am I misusing or misunderstanding decltype?

推荐答案

由于表达式 *this 不是 id-expression(即它没有命名实体,如变量),然后 decltype(*this) 给出表达式 *this 的类型.该类型是 Foo&,因此添加 const 限定符并对其进行引用不会改变任何内容:要么它默默地折叠为 Foo& (遵循引用折叠等规则),或者它是一个错误(一个 const 引用类型).我不确定哪种行为是正确的,实际上您已经找到了两个行为不同的编译器.在任何情况下都没有关系,因为这不是你想要的.

Since the expression *this is not an id-expression (i.e. it doesn't name an entity, like a variable), then decltype(*this) gives the type of the expression *this. That type is Foo&, so adding a const qualifier and making a reference to that doesn't change anything: either it silently collapse to Foo& (following rules like reference collapsing), or it's an error (a const reference type). I'm not sure which behaviour is correct, and you have in fact found two compilers which behave differently. In any case it doesn't matter because it's not what you want.

您可以使用 std::remove_reference<decltype(*this)>::type const& 代替,但这看起来有点难看.

You can use std::remove_reference<decltype(*this)>::type const& instead but that looks a bit ugly.

如果您仍然感到困惑:

int* p;
// decltype(p) is the type of the variable p (or, the declared type)
// int*

// decltype( (p) ) is the type of the expression p
// int*& because p is an lvalue

// decltype(*p) is the type of the expression *p
// int& because *p is an lvalue

相关文章