Russian Qt Forum
Ноябрь 23, 2024, 08:19 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: [1]   Вниз
  Печать  
Автор Тема: сократить написание типа лямбды  (Прочитано 6961 раз)
kambala
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4747



Просмотр профиля WWW
« : Июль 02, 2014, 20:45 »

Здравствуйте. Есть такой код (сокращенный, не относящиеся к делу части убраны):
Код
C++ (Qt)
   auto traverseGrid = [](const NumberGrid &numberGrid, std::function<const NumberCell &(const NumberGrid &numberGrid, uchar m, uchar a)> getCell)
   {
       getCell(numberGrid, 0, 1);
   };
 
   traverseGrid(_leftNumberGrid, [](const NumberGrid &numberGrid, uchar m, uchar a) { return numberGrid.cellAt(m, a); });
   traverseGrid(_topNumberGrid,  [](const NumberGrid &numberGrid, uchar m, uchar a) { return numberGrid.cellAt(a, m); });
Можно ли как-то покороче описать лямбды (не писать их огромный тип)? traverseGrid может быть и методом, не суть важно.
Записан

Изучением C++ вымощена дорога в Qt.

UTF-8 has been around since 1993 and Unicode 2.0 since 1996; if you have created any 8-bit character content since 1996 in anything other than UTF-8, then I hate you. © Matt Gallagher
Bepec
Гость
« Ответ #1 : Июль 02, 2014, 21:17 »

define не подойдёт?
Или ещё что то надо?
Записан
kambala
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4747



Просмотр профиля WWW
« Ответ #2 : Июль 02, 2014, 21:30 »

ну хотелось бы typedef например, дефайны мне не надо
Записан

Изучением C++ вымощена дорога в Qt.

UTF-8 has been around since 1993 and Unicode 2.0 since 1996; if you have created any 8-bit character content since 1996 in anything other than UTF-8, then I hate you. © Matt Gallagher
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #3 : Июль 03, 2014, 08:37 »

Хотелось бы узнать чем вызван такой синтаксис, что он дает, какую общность Вы хотели получить. По коду это не очень ясно, подробности бы не помешали

Спасибо
Записан
navrocky
Гипер активный житель
*****
Offline Offline

Сообщений: 817


Погроммист


Просмотр профиля
« Ответ #4 : Июль 03, 2014, 09:02 »

Хотелось бы узнать чем вызван такой синтаксис, что он дает, какую общность Вы хотели получить. По коду это не очень ясно, подробности бы не помешали

Спасибо

Ну я думаю, имелось ввиду сократить запись лямбды, поиск способа. Для примера лямбда на C#:

Код:
traverseGrid(_leftNumberGrid, (numberGrid, m, a) => { return numberGrid.cellAt(m, a); });

и еще раз оригинал:

Код:
traverseGrid(_leftNumberGrid, [](const NumberGrid &numberGrid, uchar m, uchar a) { return numberGrid.cellAt(m, a); });

К сожалению, тут даже typedef-ить нечего, типы параметров однословные. Разве что typedef const NumberGrid& NumberGridConstRef;. Но это не помогает сокращатить код в данном случае.
Записан

Гугль в помощь
m_ax
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2095



Просмотр профиля
« Ответ #5 : Июль 03, 2014, 10:06 »

Здравствуйте. Есть такой код (сокращенный, не относящиеся к делу части убраны):
Код
C++ (Qt)
   auto traverseGrid = [](const NumberGrid &numberGrid, std::function<const NumberCell &(const NumberGrid &numberGrid, uchar m, uchar a)> getCell)
   {
       getCell(numberGrid, 0, 1);
   };
 
   traverseGrid(_leftNumberGrid, [](const NumberGrid &numberGrid, uchar m, uchar a) { return numberGrid.cellAt(m, a); });
   traverseGrid(_topNumberGrid,  [](const NumberGrid &numberGrid, uchar m, uchar a) { return numberGrid.cellAt(a, m); });
Можно ли как-то покороче описать лямбды (не писать их огромный тип)? traverseGrid может быть и методом, не суть важно.

А чем мотивировано то, что traverseGrid должна быть именно лямбдой?

Можно например проще:

Код
C++ (Qt)
template <class R, class Arg, class F>
R traverseGrid(const Arg & arg, F function)
{
   return function(arg, 0, 1);
}
 
traverseGrid(_leftNumberGrid, [](const NumberGrid &numberGrid, uchar m, uchar a) { return numberGrid.cellAt(m, a); });
traverseGrid(_topNumberGrid,  [](const NumberGrid &numberGrid, uchar m, uchar a) { return numberGrid.cellAt(a, m); });
 
Записан

Над водой луна двурога. Сяду выпью за Ван Гога. Хорошо, что кот не пьет, Он и так меня поймет..

Arch Linux Plasma 5
kambala
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4747



Просмотр профиля WWW
« Ответ #6 : Июль 03, 2014, 12:39 »

Хотелось бы узнать чем вызван такой синтаксис, что он дает, какую общность Вы хотели получить. По коду это не очень ясно, подробности бы не помешали

Спасибо
в теле traverseGrid выполняется двойной цикл (обход сетки Улыбающийся ), тело цикла которого для двух объектов отличается лишь способом получения ячейки по индексам. сейчас подумалось, что может стоит перегрузить cellAt, чтобы не заниматься подобными вещами.
Цитировать
А чем мотивировано то, что traverseGrid должна быть именно лямбдой?
пока что написал как лямбду чтобы метод на «один чих» не создавать. в будущем скорее всего появятся еще объекты, для которых надо будет выполнять traverseGrid в подклассе.

вообще вопрос был не о traverseGrid, а о длинном типе [](const NumberGrid &numberGrid, uchar m, uchar a) Улыбающийся Пусть, например, есть 10 объектов, для которых надо написать подобную лямбду, неужели надо каждый раз этот длинный тип пропихивать (без дефайнов)? По сути он же повторяет тип из std::function в traverseGrid, может можно это как-то унифицировать?
Записан

Изучением C++ вымощена дорога в Qt.

UTF-8 has been around since 1993 and Unicode 2.0 since 1996; if you have created any 8-bit character content since 1996 in anything other than UTF-8, then I hate you. © Matt Gallagher
m_ax
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2095



Просмотр профиля
« Ответ #7 : Июль 03, 2014, 13:54 »

Если все лямбды подобны (т.е. вызывается один и тот же метод cellAt) то почему не унифицировать так:

Код
C++ (Qt)
std::function<uchar (const NumberGrid&, uchar, uchar)> traverseGrid = &NumberGrid::cellAt;
 
traverseGrid(_leftNumberGrid, m, a);
traverseGrid(_topNumberGrid, a, m);
 
 

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

Над водой луна двурога. Сяду выпью за Ван Гога. Хорошо, что кот не пьет, Он и так меня поймет..

Arch Linux Plasma 5
kambala
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4747



Просмотр профиля WWW
« Ответ #8 : Июль 03, 2014, 14:17 »

Или суть в том, что сигнатура лямбды одинакова, но реализация может сильно отличаться от случая к случаю?
изначально был именно такой вопрос. но в данном конкретном случае будет достаточно и ссылки на cellAt. спасибо за подсказку!
Цитировать
сейчас подумалось, что может стоит перегрузить cellAt, чтобы не заниматься подобными вещами.
так не получится, в другом месте код станет нелогичным
« Последнее редактирование: Июль 03, 2014, 14:29 от kambala » Записан

Изучением C++ вымощена дорога в Qt.

UTF-8 has been around since 1993 and Unicode 2.0 since 1996; if you have created any 8-bit character content since 1996 in anything other than UTF-8, then I hate you. © Matt Gallagher
kambala
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4747



Просмотр профиля WWW
« Ответ #9 : Июль 03, 2014, 14:48 »

что-то не хочет компилиться:
Код
C++ (Qt)
std::function<const NumberCell &(const NumberGrid &numberGrid, uchar m, uchar a)> x = &NumberGrid::cellAt;
Цитировать
/Users/kambala/Documents/Projects/iOS/relaks/Relaks/classes/model/puzzles/Nonogram.cpp:70:87: error: no viable conversion from '<overloaded function type>' to 'std::function<const NumberCell &(const NumberGrid &, uchar, uchar)>'
    std::function<const NumberCell &(const NumberGrid &numberGrid, uchar m, uchar a)> x = &NumberGrid::cellAt;
                                                                                      ^   ~~~~~~~~~~~~~~~~~~~
In file included from /Users/kambala/Documents/Projects/iOS/relaks/Relaks/classes/model/puzzles/Nonogram.cpp:9:
In file included from /Users/kambala/Documents/Projects/iOS/relaks/Relaks/classes/model/puzzles/Nonogram.h:12:
In file included from /Users/kambala/Documents/Projects/iOS/relaks/Relaks/classes/model/puzzles/Puzzle.hpp:15:
In file included from /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../lib/c++/v1/fstream:169:
In file included from /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../lib/c++/v1/ostream:131:
In file included from /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../lib/c++/v1/ios:216:
In file included from /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../lib/c++/v1/__locale:18:
In file included from /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../lib/c++/v1/mutex:177:
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../lib/c++/v1/functional:1448:5: note: candidate constructor not viable: no overload of 'cellAt' matching 'nullptr_t' for 1st argument
    function(nullptr_t) _NOEXCEPT : __f_(0) {}
    ^
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../lib/c++/v1/functional:1449:5: note: candidate constructor not viable: no overload of 'cellAt' matching 'const std::__1::function<const NumberCell &(const NumberGrid &, unsigned char, unsigned char)> &' for 1st argument
    function(const function&);
    ^
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../lib/c++/v1/functional:1450:5: note: candidate constructor not viable: no overload of 'cellAt' matching 'std::__1::function<const NumberCell &(const NumberGrid &, unsigned char, unsigned char)> &&' for 1st argument
    function(function&&) _NOEXCEPT;
    ^
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../lib/c++/v1/functional:1452:7: note: candidate template ignored: couldn't infer template argument '_Fp'
      function(_Fp, typename enable_if
      ^
1 error generated.

Методы объявлены так:
Код
C++ (Qt)
template <class Cell>
class Grid
{
         Cell &cellAt(uchar row, uchar column);
   const Cell &cellAt(uchar row, uchar column) const;
};
 
class NumberGrid : public Grid<NumberCell> {}
Цитировать
$ clang -v
Apple LLVM version 5.1 (clang-503.0.40) (based on LLVM 3.4svn)
Target: x86_64-apple-darwin13.3.0
Thread model: posix
« Последнее редактирование: Июль 03, 2014, 14:51 от kambala » Записан

Изучением C++ вымощена дорога в Qt.

UTF-8 has been around since 1993 and Unicode 2.0 since 1996; if you have created any 8-bit character content since 1996 in anything other than UTF-8, then I hate you. © Matt Gallagher
m_ax
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2095



Просмотр профиля
« Ответ #10 : Июль 03, 2014, 16:18 »

Правильно будет так:
Код
C++ (Qt)
std::function<const NumberCell &(const NumberGrid &, uchar, uchar)> x = &NumberGrid::cellAt;
 

Но проблема ещё и в том, что метод cellAt - перегруженный..
Не знаю как в такой ситуации std::function заставить работать..
Записан

Над водой луна двурога. Сяду выпью за Ван Гога. Хорошо, что кот не пьет, Он и так меня поймет..

Arch Linux Plasma 5
kambala
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4747



Просмотр профиля WWW
« Ответ #11 : Июль 03, 2014, 17:25 »

без имен параметров тоже пробовал, ошибка была та же. пробовал даже
Код
C++ (Qt)
auto x = &NumberGrid::cellAt;
все равно ошибка, только другая.

придется создать еще один метод, который будет сам вызывать cellAt с нужным порядком параметров (объекты-сетки на самом деле типов, производных от NumberGrid).

значит, ответом на исходный вопрос будет «невозможно, сигнатуру лямбды надо всегда писать»?
Записан

Изучением C++ вымощена дорога в Qt.

UTF-8 has been around since 1993 and Unicode 2.0 since 1996; if you have created any 8-bit character content since 1996 in anything other than UTF-8, then I hate you. © Matt Gallagher
m_ax
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2095



Просмотр профиля
« Ответ #12 : Июль 03, 2014, 17:51 »

значит, ответом на исходный вопрос будет «невозможно, сигнатуру лямбды надо всегда писать»?

Нет, "невозможно" здесь слишком громкое слово..
Например, если посмотреть в boost::phoenix то там вообще вместо лямбды можно писать сами выражения (без всяких сигнатур функций)
например можно как то так (отрывок из одного проекта):
Код
C++ (Qt)
using boost::phoenix::arg_names::arg1;
auto it = std::find_if(container.begin(), container.end(), arg1 == key);
 

Думаю, здесь  можно и как-нить более изящнее решить проблему..
Записан

Над водой луна двурога. Сяду выпью за Ван Гога. Хорошо, что кот не пьет, Он и так меня поймет..

Arch Linux Plasma 5
m_ax
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2095



Просмотр профиля
« Ответ #13 : Июль 03, 2014, 22:06 »

Вобщем у меня заработало так:

Код
C++ (Qt)
typedef const NumberCell & (NumberGrid::*const_mem_fun_type)(uchar, uchar) const;
typedef NumberCell & (NumberGrid::*mem_fun_type)(uchar, uchar);
 
std::function<const NumberCell &(const NumberGrid &, uchar, uchar)> x = static_cast<const_mem_fun_type>(&NumberGrid::cellAt);
 
 
Записан

Над водой луна двурога. Сяду выпью за Ван Гога. Хорошо, что кот не пьет, Он и так меня поймет..

Arch Linux Plasma 5
kambala
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4747



Просмотр профиля WWW
« Ответ #14 : Июль 03, 2014, 22:51 »

от старых добрых указателей никуда не деться Улыбающийся

в общем, я traverseGrid превратил в шаблонный метод, чтобы он любые сетки принимал, и пришлось добавить парочку методов в базовый класс сетки чтобы вышло коротко и красиво.
Записан

Изучением C++ вымощена дорога в Qt.

UTF-8 has been around since 1993 and Unicode 2.0 since 1996; if you have created any 8-bit character content since 1996 in anything other than UTF-8, then I hate you. © Matt Gallagher
Страниц: [1]   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.611 секунд. Запросов: 23.