о скобках в С++

Возможный дубликат:
decltype и скобки

int i=6;
decltype((i)) var5 = i;      // int& 

я просто не понимал, почему «i» в круглых скобках рассматривается как Lvalue, теперь я знал применение круглых скобок, пока не обнаружил, что в MSDN: внутренние круглые скобки заставляют оператор оцениваться как выражение, а не как членский доступ.(http://msdn.microsoft.com/en-us/library/dd537655.aspx), и я также не понял вопрос, который я не понимал в течение длительного времени.

template<typename T>
class B
{
public:
    B(T t){printf("B\n");}

};
template <typename T >
void ft(T t)
{
    t.f();
}
int _tmain(int argc, _TCHAR* argv[])
{
    B<A> b1(A());   //one function declaration, A() is regarded as fun-ptr, and b1 is a function
    B<A> b2((A())); //A() is regarded as anonymous object.
    return 0;   
}

Почему A() считается анонимным объектом, если его заключить в скобки как (A()). объяснение decltype во внутренних скобках в MSDN не может применяться к этой ситуации. может ли кто-нибудь сказать мне, есть ли объяснение функции скобок в этих двух ситуациях в стандарте С++. Как я должен понять это лучше, очень ценю это!


person Leonhart Squall    schedule 08.06.2012    source источник
comment
Вторая часть вопроса — это раздражающий анализ.   -  person jpalecek    schedule 08.06.2012


Ответы (1)


Это действительно совершенно разные ситуации.

B<A> b1(A());

Это объявление функции, поскольку оно следует синтаксису «идентификатор возвращаемого типа» ('список-объявлений-параметров')'», где список-объявлений-параметров — это список объявлений-параметров, разделенных запятыми. Результатом такого объявления является "type abstract-declarator[opt]". Кроме всего прочего, abstract-declarator может быть пустым или "'(' abstract-declarator')'". Таким образом, "A()" соответствует типу (A), за которым следует форма abstract-declarator в скобках, содержащая пустую форму abstract-declarator. Таким образом, код синтаксически является допустимым объявлением функции и анализируется как таковой.

B<A> b1((A()));

Здесь, если мы хотим пойти по пути объявления функции, нам нужно сопоставить "(A())" с объявлением параметра; однако сделать это невозможно. Так что это не объявление функции и, следовательно, должно быть объявлением переменной с прямым инициализатором.

Другая ситуация грамматически однозначна. И decltype(i), и decltype((i)) являются простыми производными от decltype. В первом случае синтаксическое дерево — это DeclType(DeclRefExpression("i")), во втором — DeclType(ParenExpression(DeclRefExpression("i"))).

Особой частью здесь являются правила для decltype. Правила decltype следующие:

  1. Если выражение является вызовом функции, результатом decltype является объявленный тип этой функции. Например. учитывая "int foo()", decltype(foo()) равен "int". Учитывая "int& foo()", decltype(foo()) равен "int&".
  2. Если выражение является выражением ссылки объявления, результатом decltype является объявленный тип этого объявления. Учитывая "int i", decltype(i) равен "int". Учитывая "int& i", decltype(i) равен "int&".
  3. Если ничего из вышеперечисленного не применимо и выражение является lvalue, результатом decltype является ссылка lvalue на тип выражения. Если выражение является lvalue типа int, результатом будет "int&".
  4. Если ни одно из приведенных выше правил не применяется, результатом decltype является тип выражения. Если выражение является rvalue типа int, результатом будет «int».

В decltype(i) выражение является declref для i. Тип i — int. Таким образом, decltype(i) равен "int". В decltype((i)) выражение является парным выражением. Неважно, что содержится в скобках — ни правило 1, ни правило 2 не применимы. Однако (i) является lvalue, поэтому применяется правило 3. Тип (i) — int, поэтому decltype((i)) — «int&».

person Sebastian Redl    schedule 08.06.2012