Я играю с функциональными возможностями С++ 11. Одна вещь, которую я нахожу странной, заключается в том, что тип лямбда-функции на самом деле НЕ является функцией < > type. Что еще, лямбда, похоже, не очень хорошо работает с механизмом ввода-вывода.
Приложен небольшой пример, в котором я тестировал перелистывание двух аргументов функции для добавления двух целых чисел. (Компилятор, который я использовал, был gcc 4.6.2 под MinGW.) В этом примере тип для addInt_f
был явно определен с использованием функции < > while addInt_l
- это лямбда, тип которой имеет тип-вывод, с помощью auto
.
Когда я скомпилировал код, функция flip
может принять явно установленную версию версии addInt, но не лямбда-версию, давая ошибку, говоря, что,
testCppBind.cpp:15:27: error: no matching function for call to 'flip(<lambda(int, int)>&)'
Следующие несколько строк показывают, что лямбда-версия (а также "сырая" версия) может быть принята, если она явно передана соответствующей функции < > type.
Итак, мои вопросы:
-
Почему именно лямбда-функция не имеет типа
function<>
в первую очередь? В маленьком примере, почемуaddInt_l
не имеетfunction<int (int,int)>
как типа вместо другого типаlambda
? С точки зрения функционального программирования, какая разница между функционально-функциональным объектом и лямбдой? -
Если есть фундаментальная причина, что эти два должны быть разными. Я слышал, что лямбда может быть преобразована в
function<>
, но они разные. Является ли это проблемой/недостатком дизайна С++ 11, проблемой реализации или есть ли преимущество в том, чтобы различать два, как это есть? Кажется, что сигнатура типаaddInt_l
сама по себе предоставила достаточную информацию о параметрах и возвращаемых типах функции. -
Есть ли способ написать лямбда, чтобы избежать вышеупомянутого явного литья типов?
Спасибо заранее.
//-- testCppBind.cpp --
#include <functional>
using namespace std;
using namespace std::placeholders;
template <typename T1,typename T2, typename T3>
function<T3 (T2, T1)> flip(function<T3 (T1, T2)> f) { return bind(f,_2,_1);}
function<int (int,int)> addInt_f = [](int a,int b) -> int { return a + b;};
auto addInt_l = [](int a,int b) -> int { return a + b;};
int addInt0(int a, int b) { return a+b;}
int main() {
auto ff = flip(addInt_f); //ok
auto ff1 = flip(addInt_l); //not ok
auto ff2 = flip((function<int (int,int)>)addInt_l); //ok
auto ff3 = flip((function<int (int,int)>)addInt0); //ok
return 0;
}