Это core issue 728, который был подан до того, как общие лямбды были предметом.
Вы упомянули общие лямбды и что они были идентичны местным классам с соответствующим членом template operator()
. Однако на самом деле их нет, а различия связаны с характеристиками реализации. Рассматривает
template <typename T>
class X {
template <typename>
void foo() {
T t;
}
};
И
template <typename T>
auto bar() {
return [] (auto) {T t;};
};
Инстанцирования этих шаблонов с <void>
будет хорошо в первом случае, но плохо сформированный во втором. Почему хорошо в первом случае? foo
не обязательно быть объективным для каждого конкретного T
, но только один из них (это будет [temp.res]/(8.1)).
Почему плохо сформировался во втором случае? Общее тело лямбды создается - частично - используя предоставленные аргументы шаблона. И причина этого частичного конкретизации является тот факт, что ...
... лексические прицелы, используемые при обработке определения функции принципиально преходящи, что означает, что задержка экземпляра некоторой части определения шаблона функции трудно поддерживать.
(Richard Smith) Мы должны создать экземпляр достаточно локального «шаблон», чтобы сделать его независимым от локального контекста (который включает в себя параметры шаблона шаблона функции ограждающей).
Это также связано с обоснованием для [expr.prim.lambda]/13, которое предусматривает, что объект неявно захвачен лямбда, если ...
называет объектные в потенциально оценивается выражением ([basic.def. odr]), где полное выражение зависит от общего параметра лямбда, объявленного в пределах области охвата лямбда-выражения .
То есть, если у меня есть лямбда, как [=] (auto x) {return (typename decltype(x)::type)a;}
, где a
некоторые переменная блок-Scope из функции включения, независимо от того, является ли ЬурейиМ членом x
«ы для void
или нет, бросок будет вызывать захват из a
, потому что мы должны решить это, не дожидаясь вызова лямбды. Для обсуждения этой проблемы см. original proposal on generic lambdas.
Суть заключается в том, что полностью откладывание экземпляра шаблона-члена несовместимо с моделью, используемой (по крайней мере одной) основной реализацией (-ами), и поскольку это ожидаемая семантика, эта функция не была введена.
Было ли это оригинальной мотивацией для этого ограничения?Он был введен когда-то в период с января по май 1994 года, без бумаги покрытия, поэтому мы можем только получить примерное представление о преобладающих понятиях из обоснования this paper «s почему локальные классы не должны быть шаблонными аргументами:
Класса шаблоны и классы, созданные из шаблона, являются глобальными объектами и не могут ссылаться на локальные объекты сущности.
Возможно, в то время один хотел КИСС.
В стандарте указано, что lambdas являются исключением. Но я предполагаю, что вас больше интересует логическое обоснование, когда вы спрашиваете, почему. – krzaq
@krzaq точно - я не понимаю, почему разработчики не используют его ... –
Мы уверены, что определение типа неименованного класса ограничено областью, в которой оно объявлено? Я всегда думал, что они сделали его глобальным, и это просто экземпляр, который локально ограничен. – NathanOliver