C++11, передача Lambda-выражения как параметра
От: vintch  
Дата: 12.01.12 16:06
Оценка:
Доброго времени суток.

Занимаюсь проектом, сейчас начал использовать некоторые прелести 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...) — буду рад ссылке.
Вариант, вида:

template <class T>
void SomeFunction(T function)
{
    function();
}


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

Таким образом, по-сути остаётся вариант — написать некий упрощённый аналог 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.s. Полезная информация по теме есть вот здесь:
http://stackoverflow.com/questions/3534812/how-does-template-parameter-of-stdfunction-work-implementation

p.p.s. Находил описание концепции лямбда-выражений в С++, описывающей, что семантически они эквивалентны вложенному классу-функтору. Если кому-то нужно, найду где я это видел, поделюсь.

Если есть мысли по этому поводу, прошу, пожалуйста, поделитесь.
c++11 c++0x lambda
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.