问题 使用decltype将其强制转换为const


我正试图解决一个问题 decltype 将大大简化事情,但我遇到了一个问题 decltype 上 *this 并添加一个 const 预选赛。下面的示例代码演示了该问题。

#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中编译,但执行会递归,直到发生堆栈溢出。

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?


8177
2017-09-14 12:22


起源

const_cast 可能会更好地表达意图。 - Cubbi
@Cubbi表达对谁的意图? - Jesse Stimpson
@Jesse:我认为他的意思 const_cast<Foo const*>(this)->bar(); 更容易 读 比任何涉及的 decltype 对于这种情况。 - ildjarn
@ildjam我的意思是建议使用const_cast来表明所有复杂的表达式都是改变constness,但是 看起来我错了。 - Cubbi
@Potatoswatter - 你抓住了我。 ;)我确实在使用 decltype 在预处理器宏中,为某个涉及const正确性的习语“生成”一些代码。我意识到预处理器不是理想的代码生成工具。 - Jesse Stimpson


答案:


既然表达了 *this 不是 ID-表达 (即,它没有命名实体,如变量),然后 decltype(*this) 给出表达式的类型 *this。那种类型是 Foo&,所以加一个 const 限定符并引用它不会改变任何东西:要么默默地崩溃到 Foo& (遵循参数折叠等规则),或者它是一个错误(一个const引用类型)。我不确定哪种行为是正确的,你实际上发现了两个行为不同的编译器。无论如何它并不重要,因为它不是你想要的。

您可以使用 std::remove_reference<decltype(*this)>::type const& 相反,但看起来有点难看。

如果你仍然困惑:

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

14
2017-09-14 14:23



std::remove_reference 适合我。感谢您的建议! - Jesse Stimpson