Рассмотрим следующий пример:
#include <functional>
#include <iostream>
using namespace std;
class Caller {
public:
Caller(function<void()> callback) {
callback();
}
};
main() {
#if defined(ONELINER)
Caller caller = [] { cout << "test"; };
#else
function<void()> fun = [] { cout << "test"; };
Caller caller(fun);
#endif // defined(ONELINER)
}
Если мы просто попытаемся скомпилировать его (с флагом -std=c++11), он благополучно завершится и отобразит test
при запуске. Однако, если мы определим компиляцию макроса ONELINER
, произойдет сбой:
prog.cpp: In function 'int main()':
prog.cpp:17:40: error: conversion from 'main()::<lambda()>' to non-scalar type 'Caller' requested
Caller caller = [] { cout << "test"; };
Я так понимаю, что это вызвано тем, что идет неявное преобразование из лямбды в std::function
и затем неявное преобразование из std::function
в Caller
, и мы не можем выполнять 2 преобразования одновременно.
Можно ли как-то заставить работать синтаксис Class object = lambda;
? Я спрашиваю, потому что недавно я играл с написанием своей собственной небольшой среды тестирования по образовательным причинам, и я подумал, что это:
UNIT_TEST(test_name) {
// test content
};
намного элегантнее, чем
UNIT_TEST_BEGIN(test_name)
// unit test
UNIT_TEST_END()
Первое может быть достигнуто с помощью лямбда-выражений, переданных в конструктор UnitTest
. Но с проблемой, которую я описал, мне пришлось использовать грязный обходной путь, например:
#define UNIT_TEST(test_name) \
::std::function<void(::Helper*)> test_name_helper; \
::UnitTest test_name ## _test = \
test_name_helper = \
[&] (::Helper* helper)
и вообще не выглядит элегантно. Но даже если это можно сделать без лямбда-выражений, я все еще заинтригован, можно ли добиться синтаксиса Class object = lamda;
.
std::function
в конце концов является шаблоном, так что я думаю, вы имеете в виду какой-то конкретный вариант использования? - person Mateusz Kubuszok   schedule 28.01.2015