Использование decltype для приведения этого к const - PullRequest
11 голосов
/ 14 сентября 2011

Я пытаюсь решить проблему, в которой 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?

1 Ответ

14 голосов
/ 14 сентября 2011

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

Вместо этого вы можете использовать std::remove_reference<decltype(*this)>::type const&, но это выглядит немного уродливо.

На случай, если вы все еще не уверены1014 *

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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...