что такое сигнатура типа лямбда-функции 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.
мне было интересно, есть ли стандартный способ получить сигнатуру типа (т. е. тип возврата и типы) его параметров любой заданной лямбды?
нет, нет.
причина, по которой я спрашиваю, что я всегда задавался вопросом, что именно тип
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 и используете их не локально, где вы не знаете подпись вызова, вы делаете это неправильно.