2016-10-25 4 views
32

Насколько я понимаю - общие лямбды преобразуются в объекты локальных структур с шаблонами 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++, чем в ошибке компилятора. Каковы причины, по которым лямбдам разрешено иметь шаблонных членов, а не местные структуры?

Я нашел this qustion, но я думаю, что ответ отчасти устарел (я не думаю, что это правда даже для C++ 11).

+4

В стандарте указано, что lambdas являются исключением. Но я предполагаю, что вас больше интересует логическое обоснование, когда вы спрашиваете, почему. – krzaq

+1

@krzaq точно - я не понимаю, почему разработчики не используют его ... –

+0

Мы уверены, что определение типа неименованного класса ограничено областью, в которой оно объявлено? Я всегда думал, что они сделали его глобальным, и это просто экземпляр, который локально ограничен. – NathanOliver

ответ

27

Это 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 почему локальные классы не должны быть шаблонными аргументами:

Класса шаблоны и классы, созданные из шаблона, являются глобальными объектами и не могут ссылаться на локальные объекты сущности.

Возможно, в то время один хотел КИСС.

+0

Показанный основной вопрос для этого, но полностью не смог его найти. Хорошо поймал. – Barry

+5

@ Барри Я знал об этом заранее, так как начал писать для него документ – Columbo

+0

Благодарим вас за всесторонний ответ. У меня было ощущение, что нет аргументов против местных классов с шаблонами членов, и ограничение связано только с предыдущей формулировкой. –

3

Я предполагаю, что проблема лежит больше в стандарте C++

Correct. Это предусмотрено в [TEMP] для шаблонов классов:

шаблона декларирование может появиться только в области видимости пространства имен или объявления области видимости класса.

и [temp.mem] для шаблонов членов:

Локальный класс типа Неушивание не должны иметь шаблоны членов.


Каковы причины лямбды разрешено иметь шаблонные членов, а не местные структуры?

Поскольку, как только у нас были лямбды в C++ 11, было сочтено, что было бы чрезвычайно полезно расширить эту концепцию, чтобы иметь общие лямбды. Для такого расширения языка был proposal, который был принят revisedand revised.

С другой стороны, пока еще не представлено предложение (насколько мне известно из краткого поиска), в котором излагается мотивация необходимости создания шаблонов членов в локальных классах, которые недостаточно решены по общей лямбде.

Если вы считаете, что это важная проблема, которая должна быть решена, не стесняйтесь submit a proposal после того, как вы изложите продуманную мотивацию к тому, почему важны шаблоны локальных членов.

+2

Что делать, если это не «важная проблема, которая должна быть решена», а «непонятный язык непоследовательно, который, очевидно, должен быть исправлен»? –

+2

@NicolBolas То же заключение действительно. Плюс вы могли бы сказать, что «очевидная языковая несогласованность» является важной проблемой. – Barry

+0

@Barry 'Если вы чувствуете, что это важная проблема, которая должна быть решена', я считаю, что это может быть важная проблема, но, как неродной английский говорящий, я бы, вероятно, отказался от формулировки :) –

 Смежные вопросы

  • Нет связанных вопросов^_^