Подтвердить что ты не робот

Используя decltype, чтобы применить это к const

Я пытаюсь решить проблему, в которой decltype значительно упростит ситуацию, но я столкнулся с проблемой, используя decltype on *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?

4b9b3361

Ответ 1

Так как выражение *this не является id-выражением (то есть оно не называет сущность, как переменную), то decltype(*this) дает тип выражения *this. Этот тип Foo&, поэтому добавление квалификатора const и ссылка на него ничего не меняет: либо он бесшумно сворачивается на Foo& (следующие правила, такие как слияние ссылок), либо это ошибка (ссылка на константу тип). Я не уверен, какое поведение правильное, и вы на самом деле нашли два компилятора, которые ведут себя по-другому. В любом случае это не имеет значения, потому что это не то, что вы хотите.

Вместо этого вы можете использовать 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