автоматическое затухание указателя лямбда - функции при переходе к шаблонной функции
Есть ли способ сделать лямбда-распад указателем, не приводя явно к правой сигнатуре? Это приведет к некоторому коду:
template<typename T> T call(T(*func)()){ return func(); }
int ptr(){ return 0; }
int main(){
auto ret1 = call(ptr);
auto ret2 = call((int(*)())([]{ return 0; }));
auto ret3 = call([]{ return 0; }); //won't compile
}
Очевидно, что вызов call
работает только в том случае, если лямбда распадается на указатель, но я предполагаю, что это может произойти только после выбора правильной перегрузки функции/шаблона. К сожалению, я могу думать только о решениях, которые включают шаблоны для создания лямбды с любой сигнатурой распада, поэтому я возвращаюсь к квадратному.2 ответа:
Вы можете изменить свою лямбду, чтобы использовать унарный оператор
+
:+[]{ return 0; }
Это работает, потому что унарный плюс может быть применен к указателям и вызовет неявное преобразование в указатель функции.
Почему бы вам излишне ограничивать себя указателями функций без дефолтных аргументов и лямбдами без захватов, полностью исключив огромное семейство функторов (например,
std::function
, любые результатыstd::bind
и все остальное, что имеет подходящийoperator()
)?Лучше просто расширить сигнатуру функции:
template <typename F> auto call(F func) -> decltype(func()) { return func(); } int ptr() { return 0; } int g(int i = 0) {return i;} int main() { auto ret1 = call(ptr); auto ret2 = call((int(*)())([]{ return 0; })); //tedious, but works auto ret3 = call([]{ return 0; }); //ok now. auto ret4 = call(g); //ok now! int i = 42; auto ret5 = call([=]{return i;}); //works, too! auto ret6 = call(std::bind(g, i)); //and so on... }