Вопрос

VS2010 частично поддерживает C++11.Я компилирую приведенный ниже код в VS2010 RTM.Я не понимаю, почему код CLS() анализируется по-разному.В строке «decltype(CLS()) obj1;» CLS() обозначает объект объекта класса.Но в строке «CLS obj2(CLS());» CLS() обозначает указатель на функцию, которая перенастраивает объект CLS без параметра.Ожидается ли такое поведение?Описано ли это в стандарте?

struct CLS
{
    int mi;
};

int _tmain(int argc, _TCHAR* argv[])
{
    decltype(CLS()) obj1;
    obj1.mi = 10;

    CLS obj2(CLS());
    obj2.mi = 10; // error C2228: left of '.mi' must have class/struct/union

    return 0;
}

ОБНОВЛЕНИЕ 08.12.2011

В C++11 7.1.6.2/1 ожидаемая строка в скобках является выражением.Компилятору просто нужно проверить, можно ли проанализировать строку как допустимое выражение.Если да, то код правильно сформирован.Таким образом, для кода «decltype(CLS()) obj1;» «CLS()» рассматривается как допустимое выражение, обозначающее определение объекта.

decltype-specifier:
    decltype ( expression )

ОБНОВЛЕНИЕ 03.01.2012

Potatoswatter дает объяснение, почему «cls obj2 (cls ());»; является объявлением, кроме определения объекта.

Все, что можно интерпретировать как выражение или объявление, является объявлением, каким бы необычным оно ни было.CLS obj2( CLS() );объявляет функцию, тип параметра которой CLS() является функцией без аргументов, возвращающей CLS, и тип возвращаемого значения — CLS.

Это было полезно?

Решение

Как уже говорили другие, это самый неприятный синтаксический анализ.Все, что может быть интерпретировано как выражение или объявление, является объявлением, каким бы необычным оно ни было.CLS obj2( CLS() ); объявляет функцию, тип параметра которой CLS() - это функция без аргументов, возвращающая CLS, и тип возвращаемого значения - CLS.

Например,

родовое слово

Решение состоит в использовании равномерной инициализации C ++ 11 :

родовое слово

или просто

родовое слово

Другие советы

Ожидается: Да

Это известно как « Самый неприятный разбор ".

CLS obj2(CLS());  // function forward declaration.

CLS obj2  = CLS(); // Creates object zero initialized.
CLS obj2;          // Creates object default initialized.
.

В аргументе decltype, ожидается выражение.Единственный способ интерпретации CLS() как выражение состоит в том, чтобы проанализировать его как созданный по умолчанию объект типа CLS.

Однако в CLS obj2(CLS()) (который, кстати, работает так же в C++03) есть два возможные разборы:Один как объявление функции и один как определение объекта.В качестве объявления функции внешние круглые скобки образуют список параметров, и ожидается, что содержимое укажет параметр (или их список), указав типы и необязательные имена.В этом анализе CLS() интерпретируется как тип функции.

Другой допустимый синтаксический анализ — это определение объекта.Для этого анализа, конечно, в скобках должно быть выражение (или их список), дающее интерпретацию CLS() как объект типа, созданный по умолчанию CLS.

Теперь в C++ есть правило: если что-то можно разобрать и как объявление, и как определение, оно будет анализироваться как объявление.То есть в данном случае будет использована первая интерпретация.

Это, конечно, порождает вопрос о почему первая интерпретация выбирается тогда, когда мы явно ожидаем здесь вторую.И ответ в том, что в противном случае это нарушит совместимость с C (а в некоторых случаях даже наши ожидания).Например, посмотрите на следующую строку:

int f();

Теперь вы согласитесь, что здесь объявляется функция, не принимающая аргументов и возвращающая int, верно?Но его также можно проанализировать как определение инициализированной по умолчанию переменной типа int.Благодаря упомянутому выше правилу оно действительно объявляет функцию, возвращающую int.

Правило, которое всегда дает ожидаемый результат, в лучшем случае было бы сложным, но, скорее всего, невозможным.

Обратите внимание, что в C++03 простой способ избежать этого для автоматических переменных заключался в добавлении к определению префикса auto:Поскольку объявления функций никогда не начинаются с auto, это заставило бы компилятор интерпретировать его как определение переменной.Поскольку старое значение auto был удален в C++11, это больше не работает (а для неавтоматических переменных оно все равно никогда не работало).

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top