C++0x lambda
От: _nn_ www.nemerleweb.com
Дата: 18.04.10 09:43
Оценка:
Что говорит стандарт (который еще не вышел) насчет этого :

auto f0 = [](int x) { return [=](int y) { return x + y; }; };


VC выдает:

error C3499: a lambda that has been specified to have a void return type cannot return a value


А так работает, но приходится обворачивать лямбду в std::function.
auto f1 = [](int x) -> std::function<int(int)> { return [=](int y) { return x + y; }; };
www.nemerleweb.com
Re: C++0x lambda
От: remark Россия http://www.1024cores.net/
Дата: 18.04.10 10:09
Оценка:
Здравствуйте, _nn_, Вы писали:

__>А так работает, но приходится обворачивать лямбду в std::function.

__>
__>auto f1 = [](int x) -> std::function<int(int)> { return [=](int y) { return x + y; }; };
__>


Может что-то типа такого попробовать:
auto f1 = [](int x) -> decltype([=](int y) {}) { return [=](int y) { return x + y; }; };



1024cores &mdash; all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re[2]: C++0x lambda
От: _nn_ www.nemerleweb.com
Дата: 18.04.10 11:12
Оценка:
Здравствуйте, remark, Вы писали:

R>Здравствуйте, _nn_, Вы писали:


__>>А так работает, но приходится обворачивать лямбду в std::function.

__>>
__>>auto f1 = [](int x) -> std::function<int(int)> { return [=](int y) { return x + y; }; };
__>>


R>Может что-то типа такого попробовать:

R>
R>auto f1 = [](int x) -> decltype([=](int y) {}) { return [=](int y) { return x + y; }; };

R>


R>


Хороший вопрос получился. Можно ли лямбду в decltype засунуть ?
VC не умеет:
auto f = [](int) { return 1;};
typedef decltype(f) a; // OK


typedef decltype([](int) { return 1; }) aa;

error C3477: a lambda cannot appear in an unevaluated context


P.S.
У кого GCC под рукой есть, проверьте пожалуйста.
www.nemerleweb.com
Re: C++0x lambda
От: Masterkent  
Дата: 18.04.10 11:48
Оценка:
_nn_:

__>Что говорит стандарт (который еще не вышел) насчет этого :


__>
auto f0 = [](int x) { return [=](int y) { return x + y; }; };


__>VC выдает:

__>

error C3499: a lambda that has been specified to have a void return type cannot return a value

5.1.2/4:
If a lambda-expression does not include a trailing-return-type, it is as if the trailing-return-type denotes the following type:

— if the compound-statement if of the form
    { return attribute-specifier opt expression ; }
the type of the returned expression after lvalue-to-rvalue conversion (4.1), array-to-pointer conversion
(4.2), and function-to-pointer conversion (4.3);

— otherwise, void.

Видимо, VC++ не прав. Похоже, он почему-то не считает lambda-выражение за выражение. На всякий случай попробуй обрамить внутреннее lambda-выражение круглыми скобочками — может, это заставит его передумать
Re[2]: C++0x lambda
От: Masterkent  
Дата: 18.04.10 11:57
Оценка: 5 (2)
remark:

R>Может что-то типа такого попробовать:

R>
auto f1 = [](int x) -> decltype([=](int y) {}) { return [=](int y) { return x + y; }; };


Так точно не должно работать. Lambda-выражения не могут встречаться в операнде decltype:

5.1.2/2:
A lambda-expression shall not appear in an unevaluated operand (Clause 5).

Кроме того, типы даже одинаковых lambda-выражений уникальны:

5.1.2/3:
The type of the lambda-expression (which is also the type of the closure object) is a unique, unnamed nonunion class type — called the closure type — whose properties are described below.

#include <iostream>
#include <typeinfo>

int main()
{
    auto f1 = [](int) { return 1;};
    auto f2 = [](int) { return 1;};
    std::cout << int(typeid(f1) == typeid(f2)) << std::endl;
    // должен быть выведен 0
}
Re[3]: C++0x lambda
От: Masterkent  
Дата: 18.04.10 12:00
Оценка: +1
_nn_:

__>P.S.

__>У кого GCC под рукой есть, проверьте пожалуйста.

Вот такой пример
#include <iostream>

int main()
{
    auto f0 = [](int x) { return ([=](int y) { return x + y; }); };
    std::cout << f0(11)(22) << std::endl;
}

GNU C++ 4.5 успешно компилирует (и программа выводит ожидаемые 33).
Re: C++0x lambda
От: _nn_ www.nemerleweb.com
Дата: 18.04.10 12:13
Оценка:
Здравствуйте, _nn_, Вы писали:

Ура ! Получилось

#include <functional>
#include <iostream>

int main()
{
    // No decltype(lambda)
    // Make a dummy lambda + decltype
    auto q = [](int x) { return x; };
    typedef decltype(q) int_to_int;

    // f1: int -> int    
    auto f1 = [](int x) -> int_to_int
    {
        // f2: int * int -> int
        auto f2 = ([=](int y) { return x + y; });
        // Cast!
        return reinterpret_cast<int_to_int&>(f2);
    };

    // Check :)
    std::cout << f1(1)(2);

    return 0;
}


Осталось узнать насколько законно это делать.
Походу баг этот в VC2010 не исправят сегодня.
www.nemerleweb.com
Re[2]: C++0x lambda
От: Masterkent  
Дата: 18.04.10 15:41
Оценка: 12 (2) :))) :))) :))) :))) :))) :)))
_nn_:

__>Осталось узнать насколько законно это делать.


УК РФ, Статья 273. Создание, использование и распространение вредоносных программ для ЭВМ.
Срок до семи лет.
Re[4]: C++0x lambda
От: CreatorCray  
Дата: 18.04.10 21:07
Оценка:
Здравствуйте, Masterkent, Вы писали:

M>GNU C++ 4.5 успешно компилирует (и программа выводит ожидаемые 33).

С ICC 11.1 тоже всё ок.
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[3]: C++0x lambda
От: remark Россия http://www.1024cores.net/
Дата: 19.04.10 07:04
Оценка:
Здравствуйте, Masterkent, Вы писали:

R>>Может что-то типа такого попробовать:

R>>
M>auto f1 = [](int x) -> decltype([=](int y) {}) { return [=](int y) { return x + y; }; };
M>


M>Так точно не должно работать. Lambda-выражения не могут встречаться в операнде decltype:


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

Да, это ("decltype([=](int y) {})") было определенно глупо, тип по-любому будет засисеть от закапчуренных переменных (а тут ещё дополнительное требование, что он уникальный).

Проверил на студии, она действительно генерит уникальные типы. И то хорошо, у меня почему-то было ощущение, что она для одинаковых лямбд сгенерит одинаковый тип, и у нас будет ещё одно кривое различие в компиляторах на ближайшие 10 лет Но она всё равно отличилась, на "typeid(x1) == typeid(x2)" сказала "binary '==' : 'const type_info' does not define this operator or a conversion to a type acceptable to the predefined operator".


1024cores &mdash; all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re[2]: C++0x lambda
От: March_rabbit  
Дата: 20.04.10 09:30
Оценка: :))) :))) :))) :))
Здравствуйте, _nn_, Вы писали:

__>Здравствуйте, _nn_, Вы писали:


__>Ура ! Получилось


__>
__>#include <functional>
__>


__>Осталось узнать насколько законно это делать.

__>Походу баг этот в VC2010 не исправят сегодня.
извините, а это что за брэйнфак такой?
вроде синтаксис отдаленно плюсы напоминает......
Re: C++0x lambda
От: _nn_ www.nemerleweb.com
Дата: 21.04.10 12:13
Оценка:
Здравствуйте, _nn_, Вы писали:

Тек кого волнует этот баг.
Голосуйте Microsoft Connect
www.nemerleweb.com
Re[2]: <function>
От: dipso  
Дата: 03.05.10 19:35
Оценка:
А как это std::function в конструктор лямбду принимает?Пробовал пройтись дебаггером — помоему хак.Кроме этого сам объект больше 20 байт что в gcc,что в msvc.А хотелось бы что-нибудь вида lambda<int()> нормального размера.Понятно что std::function расчитан на все случаи жизни и это не могло не сказаться на размерах объекта,но sizeof(lambda) что в gcc,что в msvc — 1 байт.Но кажется лямбды нельзя пихать в sizeof,хотя можно предположить что это индекс в таблице указателей на них.Кто что думает?Пускай даже тоже хак.
Re[3]: <function>
От: _nn_ www.nemerleweb.com
Дата: 04.05.10 07:07
Оценка:
Здравствуйте, dipso, Вы писали:

D>А как это std::function в конструктор лямбду принимает?Пробовал пройтись дебаггером — помоему хак.Кроме этого сам объект больше 20 байт что в gcc,что в msvc.А хотелось бы что-нибудь вида lambda<int()> нормального размера.Понятно что std::function расчитан на все случаи жизни и это не могло не сказаться на размерах объекта,но sizeof(lambda) что в gcc,что в msvc — 1 байт.Но кажется лямбды нельзя пихать в sizeof,хотя можно предположить что это индекс в таблице указателей на них.Кто что думает?Пускай даже тоже хак.


boost::function у вас вопрос не вызывает ?

std/boost::function принимает в шаблоне прототип функции и таким образом знает сколько надо максимум выделить памяти для передачи всех аргументов.

int main()
{
  auto x = []() { return 1; };

  std::function<int(void)> xx(x);
}


Аналогично
int f() { return 1; }

int main()
{
  int (*x)() = &f;

  boost::function<int(void)> xx(x);
}
www.nemerleweb.com
Re[3]: C++0x lambda
От: _nn_ www.nemerleweb.com
Дата: 11.04.11 15:36
Оценка:
Здравствуйте, Masterkent, Вы писали:

M>_nn_:


__>>Осталось узнать насколько законно это делать.


M>УК РФ, Статья 273. Создание, использование и распространение вредоносных программ для ЭВМ.

M>Срок до семи лет.

Кстати согласно:


http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2010/n3052.html

5.1.2.6

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.


[](int x) -> int может привестись к int(*)(int).
Следовательно может код даже законен ?
www.nemerleweb.com
Re[4]: C++0x lambda
От: Kolobrodin Россия  
Дата: 11.04.11 16:02
Оценка:
Здравствуйте, Masterkent, Вы писали:

M>_nn_:


__>>P.S.

__>>У кого GCC под рукой есть, проверьте пожалуйста.

M>Вот такой пример

M>
#include <iostream>

M>int main()
M>{
M>    auto f0 = [](int x) { return ([=](int y) { return x + y; }); };
M>    std::cout << f0(11)(22) << std::endl;
M>}

M>GNU C++ 4.5 успешно компилирует (и программа выводит ожидаемые 33).

MinGW 4.5 тоже отработал.
Неоконченная мысль всегда казалась Шри Япутре слишком
Re[4]: C++0x lambda
От: Masterkent  
Дата: 12.04.11 15:36
Оценка:
_nn_:

__>Кстати согласно:



__>http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2010/n3052.html


__>

__>5.1.2.6

__> 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.


__>[](int x) -> int может привестись к int(*)(int).

__>Следовательно может код даже законен ?

В том коде, что с reinterpret_cast, однозначное undefined behavior. Вот такой результат тебя устроит?
Re[5]: C++0x lambda
От: _nn_ www.nemerleweb.com
Дата: 12.04.11 15:57
Оценка:
Здравствуйте, Masterkent, Вы писали:

__>>[](int x) -> int может привестись к int(*)(int).

__>>Следовательно может код даже законен ?

M>В том коде, что с reinterpret_cast, однозначное undefined behavior.

Это понятно.

M>Вот такой результат тебя устроит?

Да уж. UB оно UB.

Остается только ждать фикса бага.

Кстати, как оказалось в VC есть оптимизация для std::function.
А это означает, что проблема решается просто и эффективно.
www.nemerleweb.com
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.