Почему лямбда не допускается при создании шаблона? - PullRequest
0 голосов
/ 03 декабря 2018

В настоящее время я работаю над некоторым кодом, в котором мне нужно использовать лямбду в качестве параметра шаблона, как в следующем примере:

#include <iostream>

template<void(*func)(int)>
struct FunctionCaller{
    FunctionCaller() {func(5);}
};

void RealFunction(int i){
    std::cout << i*2 << std::endl;
}

int main(){
    FunctionCaller<[](int i){std::cout << i << std::endl;}> caller; //should print 5
    FunctionCaller<RealFunction> caller2; //should print 10
    return 0;
}

Я попытался скомпилировать этот пример с недавним (C ++ 17поддержка) версий GCC и Clang (версии 8.2.1 и 7.0.0 соответственно) для получения различных ошибок, которые равносильны лямбда-выражениям, не допускаемым в аргументах шаблона.Я использую правильные флаги компилятора, чтобы включить поддержку C ++ 17.

Это, однако, мне кажется, что это должно работать, потому что книга C ++ Primer 5th edition говорит, что любое константное выражение может использоваться для невведите аргументы шаблона, и в C ++ 17, и в этом посте о переполнении стека говорится, что лямбда является константным выражением в C ++ 17 и более поздних версиях.

После обширных исследований кажется, что стандарт C ++ 17 явно запрещает лямбда-выражения в качестве параметра шаблона.В чем причина этого ограничения?Что взрывается, если его нет на месте?

РЕДАКТИРОВАТЬ: Этот вопрос содержит некоторую соответствующую информацию, но он только говорит о том, что это ограничение существует, чтобы препятствовать тому, чтобы лямбды появлялись в сигнатуре метода, безлюбая информация о том, почему это проблематично.

1 Ответ

0 голосов
/ 03 декабря 2018

После некоторого поиска я нашел изменение, которое ввело это ограничение: основной выпуск 1607 .В нем говорится:

Возникло дальнейшее обсуждение относительно лямбда-выражений в сигнатурах шаблонов функций.Хотя ограничение на то, что лямбда-выражения не могут отображаться как недооцененные операнды (пункт 8.1.5 [expr.prim.lambda]), было направлено на то, чтобы избежать необходимости иметь дело с ними в сигнатурах шаблонов функций, тот факт, что8.20 [expr.const] обрабатывает неоцененные подвыражения отдельно от неоцененных операндов, открывая еще один путь для лямбда-выражений в сигнатурах шаблонов, например,

template<typename T>
void f(int [(0 && [] { for (auto x : T()) {} }, 1)]);

Core предоставил EWG 4 опции,и они выбирают тот, который у нас есть в C ++ 17 и ранее: запрещать лямбды в сигнатуре - так что аргументы шаблона и т. д.

Теперь, почему лямбды не должны появляться в сигнатуре шаблона функции?Это объясняется в N2903 :

Кроме того, это переписывание добавляет ограничение, запрещающее использование лямбда-выражений в операнде оператора sizeof, оператора alignof,или decltype спецификатор.Это ограничение - предложенное Дагом Грегором и Джоном Спайсером - позволяет избежать серьезных трудностей реализации с выводом аргументов шаблона (например, это устраняет необходимость кодировать произвольные последовательности операторов в искаженных именах).

...