Насколько я понимаю — родовые лямбды превращаются в объекты локального масштаба с шаблонами operator()
, Это делает универсальный лямбда очень мощным и простым в использовании инструментом. С другой стороны, можно создавать структуры, вложенные в функцию, если, однако, структура имеет шаблонный член, например:
#include <iostream>
int main() {
struct inner {
template <class T>
void operator()(T &&i) { }
};
return 0;
}
или сам по себе шаблон:
int main() {
template <class T>
struct inner {
void operator()(T &&i) { }
};
return 0;
}
Компилятор, похоже, имеет проблему с компиляцией:
error: invalid declaration of member template in local class
а также
error: a template declaration cannot appear at block scope
Я предполагаю, что проблема лежит больше в стандарте c ++, чем в ошибке компилятора. По каким причинам лямбдам разрешено иметь шаблонных членов, а не местные структуры?
я нашел это питание, но я думаю, что ответ отчасти устарел (я не думаю, что это правда даже для c ++ 11).
Это основной вопрос 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)).
Почему плохо сформирован во втором случае? Базовое тело лямбды создается — частично — с использованием предоставленных аргументов шаблона. И причиной этого частичного воплощения является тот факт, что …
… Лексические области действия, используемые при обработке определения функции, являются в основном временными, что означает, что задержка создания экземпляра некоторой части определения шаблона функции трудно поддерживать.
(Ричард СмитМы должны создать достаточно экземпляра локального «шаблона», чтобы сделать его независимым от локального контекста (который включает параметры шаблона шаблона включающей функции).
Это также связано с обоснованием
[Expr.prim.lambda] / 13, который обязывает, что сущность неявно захвачена лямбда, если она …
называет сущность в потенциально оцененном выражении ([basic.def.odr]), где полное выражение зависит от общего лямбда-параметра, объявленного в пределах досягаемости лямбда-выражение.
То есть, если у меня есть лямбда-лайк [=] (auto x) {return (typename decltype(x)::type)a;}
, где a
некоторая переменная области блока из функции включения, независимо от того, x
Тип пользователя typedef предназначен для void
или нет, актерский состав вызовет захват a
потому что мы должны решить это, не дожидаясь вызова лямбды. Для обсуждения этой проблемы см. оригинальное предложение на общие лямбды.
Суть в том, что полное откладывание создания экземпляра шаблона элемента несовместимо с моделью, используемой (по крайней мере, одной) основной (-ыми) реализацией (-ями), и, поскольку это ожидаемая семантика, функция не была представлена.
Это была первоначальная мотивация для этого ограничения? Он был введен где-то между январем и маем 1994 года, и в нем не было никаких документов, поэтому мы можем получить лишь приблизительное представление о преобладающих понятиях из Эта бумагаОбоснование того, почему локальные классы не должны быть шаблонными аргументами:
Шаблоны классов и классы, сгенерированные из шаблона, являются глобальной областью действия.
объекты и не могут ссылаться на объекты локальной области.
Возможно, тогда кто-то хотел поцеловать.
Я предполагаю, что проблема лежит больше в стандарте C ++
Правильный. Это предусмотрено в [temp] для шаблонов классов:
Шаблон декларирование может появляться только как область видимости пространства имен или объявление области класса.
и [temp.mem] для шаблонов элементов:
Локальный класс не замыкающего типа не должен иметь шаблонов членов.
По каким причинам лямбдам разрешено иметь шаблонных членов, а не местные структуры?
Поскольку, как только у нас появились лямбды в C ++ 11, считалось, что было бы чрезвычайно полезно расширить эту концепцию, чтобы иметь общие лямбды. Был предложение для такого расширения языка, которое было пересмотренный и пересмотрен и принят.
С другой стороны, еще не было представлено предложение (насколько я знаю из краткого поиска), в котором изложена мотивация необходимости шаблонов элементов в локальных классах, которая не может быть адекватно решена с помощью общей лямбды. ,
Если вы чувствуете, что это важная проблема, которую необходимо решить, не стесняйтесь подать предложение после выкладки вдумчивой мотивации, почему местные шаблоны участников важны.