что такое сигнатура типа лямбда-функции C++11 / 1y?

мне было интересно, есть ли стандартный способ получить сигнатуру типа (т. е. тип возврата и типы) его параметров любой заданной лямбды?

причина, по которой я спрашиваю, что я всегда задавался вопросом, что именно тип auto в декларации как auto l =[](int x,int y)->int{return x+y;}. В других случаях использования auto, это удобство и более короткая Альтернатива для более длинного имени типа. Но для лямбд есть ли альтернативный способ объявить лямбда-переменную?

мой понимание заключается в том, что стандартная лямбда-это не что иное, как объект функции, и это ее собственный тип. Таким образом, даже если два lambdas имеют одинаковый тип возврата и типы параметров, они все равно являются двумя разными, несвязанными классами/функторами. Но это есть способ захватить тот факт, что они одинаковы с точки зрения подписи типа?

Я думаю, что подпись типа, которую я ищу, может быть чем-то вроде std::function<> объект правильного типа.

более полезное/вопрос если можно извлечь сигнатуру типа, можно написать общую функцию-оболочку для преобразования любой лямбда-функции в std::function объект того же типа подписи.

4 ответов


по данным можно ли выразить " тип " лямбда-выражения?, на самом деле есть простой способ в текущем C++ (без необходимости c++1y) выяснить типы return_type и параметров лямбды. Адаптируя это, нетрудно собрать std::function тип печатной подписи (называется f_type ниже) для каждой лямбды.

I. С этим абстрактным типом на самом деле можно иметь альтернативный способ auto для выражения сигнатуры типа a лямбда, а именно function_traits<..>::f_type ниже. Примечание:f_type не является реальным типом лямбды, а скорее сводкой сигнатуры типа лямбды в функциональных терминах. Однако это, вероятно, более полезно, чем реальный тип лямбды, потому что каждый лямда-своя типа.

как показано в коде ниже, как можно использовать vector<int>::iterator_type i = v.begin() можно сделать function_traits<lambda>::f_type f = lambda, что является альтернативой таинственному auto. Конечно, это сходство чисто формальное. Код ниже приводится преобразование лямбды в std::function стоимостью стирания типа на строительство std::function объект и небольшая стоимость для совершения косвенного вызова через


вы правы, типы лямбд C++11 являются анонимными и уникальными для экземпляра. the std::function тип может хранить ссылки на любой вид лямбда, с которым я столкнулся, но, как говорят, есть хит производительности.

попробовать

std::function<int (int, int)> f = [](int x, int y) -> int { 
    return x + y; 
};

Примечание -> int можно опустить в не неоднозначных сценариях, таких как этот.

в C++14 позволяет нам писать

std::function<int (int, int)> f = [](auto x, auto y) { 
    return x + y; 
};

что удобно для длинных имен типа.

как отметил @Jonathan Wakely, этот подход захватывает определенный экземпляр с помощью функции std::с фиксированными аргументами шаблона. В C++14 можно указать переменные шаблона. Кроме того, также на C++14 лямбда-параметры могут иметь свои типы, выводимые через auto, учитывая следующее:

template<class T>
std::function<T (T, T)> g = [](auto x, auto y) -> auto {
    return x + y;
};

в настоящее время VC++ и GCC, похоже, не поддерживают шаблоны объявлений переменных на уровне функций, но разрешают их на члене, пространстве имен и глобальных объявлениях. Я не уверен, является ли это ограничение или нет исходит из спецификации.

примечание: Я не использую clang.


В C++1y есть общие лямбды и нет одной подписи вызова (operator()() - это шаблон).


мне было интересно, есть ли стандартный способ получить сигнатуру типа (т. е. тип возврата и типы) его параметров любой заданной лямбды?

нет, нет.

причина, по которой я спрашиваю, что я всегда задавался вопросом, что именно тип auto в декларации как auto l =[](int x,int y)->int{return x+y;}.

это неопределенный тип класса, созданный реализацией. Весь смысл lambdas в том, что они " анонимны функции", т. е. вы не знаете их тип.

Если вам нужен известный тип, напишите тип объекта функции.

в других случаях использования auto это удобство и более короткая Альтернатива для более длинного имени типа. Но для лямбд есть ли альтернативный способ объявить лямбда-переменную?

нет.

если вы хотите объявить тип, то не использовать лямбда-выражение.

мое понимание что стандартная лямбда - это не что иное, как объект функции, и это ее собственный тип. Таким образом, даже если два lambdas имеют одинаковый тип возврата и типы параметров, они все равно являются двумя разными, несвязанными классами/функторами.

правильно. Каждое выражение lamda генерирует уникальный тип.

но это есть способ захватить тот факт, что они одинаковы с точки зрения подписи типа?

нет, нет языка, чтобы что.

Я думаю, что сигнатура типа, которую я ищу, может быть чем-то вроде объекта std::function правильных типов.

даже если бы это было возможно в C++11, это не помогло бы в C++14, где лямбда-выражения могут принимать любое число и любой тип аргумента, например [](auto... a) { }

и в любом случае, если вы не знаете сигнатуру вызова вашей лямбда-функции, я бы сказал, что вы используете лямбды неправильно. Когда ты пишешь лямбду, ты должен знать. каковы его свойства, поэтому либо используйте его сразу, либо поместите его в std::function (или какой-либо другой тип, который захватывает его подпись вызова) как можно раньше, когда вы знаете его свойства. Если вы создаете lambdas и используете их не локально, где вы не знаете подпись вызова, вы делаете это неправильно.