Ответ 1
Не существует специального правила, касающегося неконтегрированных приложений decltype
(т.е. [expr.prim.lambda]/20 не применяется). Таким образом, мы просто возвращаемся к обычному определению decltype
, в котором указывается, что если операнд является id-выражением, полученный тип является только объявленным типом объекта и не является ссылочным типом. Следовательно, VС++ ошибочен.
NB: неважно, захвачен ли dict
или нет, потому что & para; 17:
Каждое id-выражение внутри составного оператора лямбда-выражения , которое является неприемлемым (3.2) объекта, захваченного копией, преобразуется в доступ к соответствующему неназванному элементу данных из Тип закрытия. [Примечание: Идентификатор, не являющийся неприемлемым, относится к исходному объекту, никогда не принадлежащему члену тип закрытия. Более того, такое id-выражение не вызывает неявный захват объекта. - конец примечание]
decltype
never odr - использует любой из своих операндов или супеперад. Это правило иногда становится довольно проблематичным, например. как показано в ключевой вопрос 958:
int f (int&); void* f (const int&); int main() { int i; [=] ()-> decltype(f(i)) { return f(i); }; }
Здесь decltype(f(i))
использует не const
i
из охватывающей области. Однако, поскольку лямбда не mutable
, i
в теле на самом деле const
, поэтому тип возвращаемого возврата неверен. CWG пришел к выводу, что это возникает слишком редко, чтобы стоить решения.