Занимаюсь проектом, сейчас начал использовать некоторые прелести C++0x (компилятор, AVR GCC, пока что не поддерживает полностью C++11).
Вроде бы всё вполне понятно, но не могу решить одну проблему.
Суть:
typedef void (*func_type)();
void SomeFunction(func_type function)
{
function();
}
int main()
{
int someVar = 42;
SomeFunction([] () -> void { /* Do Nothing */ }); // Случай 1
SomeFunction([&] () -> void { someVar++; }); // Случай 2
}
Согласно стандарту C++11 в первом случае я имею полное право вот так вот писать лямбда-выражение.
Компилятор неявно приведёт его к указателю на функцию и всё замечательно.
Но вот во втором случае всё не так просто. Случай 2 использует лямбда-функцию с замыканием, подтягивая локальную переменную.
И в таком случае естественно компилятор не приводит её к указателю на функцию, отказывается компилировать.
Мне нужно реализовать код, подобный второму случаю.
STL под AVR GCC я не нашел, да если бы и нашёл — подозреваю, он был бы чертовски тяжелым. Поэтому, пожалуйста, std::function не предлагать.
Но если кто знает где взять STL под AVR GCC (я пишу AVR GCC, хотя в сущности GCC он и в Африке GCC...) — буду рад ссылке.
Вариант, вида:
пожалуйста тоже не предлагать, технически не подходит под задачу (не хочу во всех подробностях расписывать почему).
Таким образом, по-сути остаётся вариант — написать некий упрощённый аналог std::function. Но я в упор не могу представить, как соорудить
такой шаблон.
Лучшее что на сегодня вышло, это вот (следующий код — только набросок, без какого-либо внятного стиля):
class Func2 {
public:
class Invoker {
public:
virtual int Invoke()=0;
};
template <class T>
class intFunc : public Invoker {
public:
T f;
intFunc(T t)
: f(t) {}
virtual int Invoke()
{
return f(1);
}
};
Invoker* invoker;
template <class T>
Func2(T f)
{
invoker = new intFunc<T>(f);
}
int Invoke()
{
return invoker->Invoke();
}
};
void func(Func2 f)
{
a = f.Invoke();
}
int main(void)
{
int a = 0;
func([&a](int)->int { a++; return a; });
}
В общем — работает, но "работает" — далеко не показатель успеха, увы.
Во-первых очень не хочется использовать память кучи, которую потом ещё и освобождать как-то нужно.
Во-вторых, с таким подходом я не представляю как предопределять тип возвращаемого значения и тип параметров.
Цель всего мероприятия — честно говоря, носит скорее спортивный характер, нежели сугубо практический На практике конечно же я могу обойтись без лямбда-выражения,
заменив его.. да хоть вложенным классом-функтором. Но очень бы хотелось решить задачу.
p.p.s. Находил описание концепции лямбда-выражений в С++, описывающей, что семантически они эквивалентны вложенному классу-функтору. Если кому-то нужно, найду где я это видел, поделюсь.
Если есть мысли по этому поводу, прошу, пожалуйста, поделитесь.
Здравствуйте, vintch, Вы писали:
V>Если есть мысли по этому поводу, прошу, пожалуйста, поделитесь.
могу посоветовать погуглить по словам "fast delegates"
возможно, найдете что-то полезное
Re: C++11, передача Lambda-выражения как параметра
Здравствуйте, k06a, Вы писали:
K>Попробуйте по ссылке лямбду в функции получать.
Идея вполне хороша, вот только — какого типа должна быть ссылка?
Если говорить об обычной функции, то всё понятно.
А какой тип у замкнутой лямбда функции? Тут то неприятный сюрприз — её тип уникален для каждой функции,
даже если ихний код будет символ-в-символ одинаковым
Единственный способ (из мне известных) получить одновременно собственно лямбда-функцию и её тип, это:
int someVar = 0;
auto lambdaFunction = [&] () -> void { someVar++ };
Здесь:
lambdaFunction — идентификатор функции
decltype(lambdaFunction) — её тип
Но всё это локально, как его передать нужной функции то...
Re[2]: C++11, передача Lambda-выражения как параметра
Здравствуйте, uzhas, Вы писали:
U>Здравствуйте, vintch, Вы писали:
V>>Если есть мысли по этому поводу, прошу, пожалуйста, поделитесь. U>могу посоветовать погуглить по словам "fast delegates" U>возможно, найдете что-то полезное
Искал. Не нашёл. Вернее нашёл, но то, что я нашёл — никаким боком не коррелирует с лямбдами((
Re[3]: C++11, передача Lambda-выражения как параметра
Здравствуйте, k06a, Вы писали:
K>Здравствуйте, vintch, Вы писали:
V>>Идея вполне хороша, вот только — какого типа должна быть ссылка?
K>Я имел ввиду написать так:
K>
Такая функция не сможет принять аргументом замкнутую лямбда-функцию по той простой причине, что её тип не будет соответствовать void ().
K>И вообще не проще ли писать шаблоном вместо тайпдефа функции:
K>
м.. Вы читали мой первый пост? Мне нужно любую замкнутую лямбда-функцию (каждая из которых будет иметь одинаковые параметры и тип возвращаемого значения),
которая по-определению, каждая, будет иметь свой тип, привести к некоему универсальному типу, позволяющему её вызвать.
Ну то есть в сущности мне нужно её делегировать. При решении этой задачи через функцию-шаблон, я просто получу N инстанированных шаблонов для N лямбда-функций и соответственно N типов функций. И как мне их сложить в массив, например?
Re[4]: C++11, передача Lambda-выражения как параметра
Здравствуйте, k06a, Вы писали:
K>Недавно ковырялся с лямбдами... Насколько я понял... K>Лямбды с замыканиями — нельзя копировать.
Можно. Не уверен насчёт, буквально, копирования; но делегировать тем или иным образом — можно.
Просмотрите мой пример в конце первого поста. Он работает. Но он очень громоздкий и неуклюжий, не удобен в использовании.
Re: C++11, передача Lambda-выражения как параметра
Здравствуйте, vintch, Вы писали:
V>Согласно стандарту C++11 в первом случае я имею полное право вот так вот писать лямбда-выражение. V>Компилятор неявно приведёт его к указателю на функцию и всё замечательно.
Можно ссылку на пункт стандарта?
ICC на обе строки говорит:
error: no suitable conversion function from "lambda []()->void" to "func_type" exists
SomeFunction([] () -> void { /* Do Nothing */ }); // Случай 1
^
error: no suitable conversion function from "lambda []()->void" to "func_type" exists
SomeFunction([&] () -> void { someVar++; }); // Случай 2
^
И что то мне кажется что он прав.
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Забанили по IP, значит пора закрыть эту страницу.
Всем пока
Re[2]: C++11, передача Lambda-выражения как параметра
"The closure type for a lambda-expression with no lambda-capture has a public non-virtual non-explicit const conversion function to pointer to function having the same parameter and return types as the closure type’s function call operator. The value returned by this conversion function shall be the address of a function that, when invoked, has the same effect as invoking the closure type’s function call operator."
Здравствуйте, vintch, Вы писали:
V>Доброго времени суток.
V>Занимаюсь проектом, сейчас начал использовать некоторые прелести C++0x (компилятор, AVR GCC, пока что не поддерживает полностью C++11).
Кучу саму по себе не боитесь использовать для AVR? Или у вас внешнее ОЗУ прицеплено?
Сигнатура гвоздями приколочена, или просто есть требование, чтобы она была совместимой с Си?
В последнем случае можно и нужно сделать колбек с аргументом (либо интерфейс с методом, что по сути является колбеком с аргументом).
А уж как протащить в него произвольное замыкание — тут много подходов.
Например http://rsdn.ru/forum/cpp/4545231.1.aspx
А если всё-таки приколочена — придётся или генерировать машинные коды (сомневаюсь, что на микроконтроллере такое позволено), или завести глобальный пул функций и их аргументов, и далее как с колбеком-с-параметром.
Перекуём баги на фичи!
Re[2]: C++11, передача Lambda-выражения как параметра
Здравствуйте, enji, Вы писали:
E>Здравствуйте, vintch, Вы писали:
V>>Доброго времени суток.
V>>Занимаюсь проектом, сейчас начал использовать некоторые прелести C++0x (компилятор, AVR GCC, пока что не поддерживает полностью C++11).
E>Кучу саму по себе не боитесь использовать для AVR? Или у вас внешнее ОЗУ прицеплено?
Честно — страшно) Но я перечитал документацию, просмотрел исходники malloc, потестил всё это дело и пришел к выводу, что, да, можно использовать.
Но осторожно и ни в коем случае не применять для размещения объектов, чей размер диктуется внешними условиями (появляется риск фрагментации памяти).
E>А по теме — вот тут подробно разжевано http://habrahabr.ru/blogs/cpp/78299/
Спасибо, но не нашёл там ни слова о лямбда-выражениях.
Re: C++11, передача Lambda-выражения как параметра
Спасибо всем за участие, проблему разрулили.
Если кому интересно — смотрите пример в моём первом сообщении топика, в самом конце.
Там основа. Я её просто доработал и приукрасил. А чтобы избежать кучи
(что не возможно сделать полностью) — можно применять поле класса, а если его недостаточно — обращаться к куче.
К слову, подобным образом реализован std::function из STL. Отдельное спасибо tchr, который помог разобраться с кодом STL.
Когда оформлю всё, покажу реализацию.