Этот баннер — требование Роскомнадзора для исполнения 152 ФЗ.
«На сайте осуществляется обработка файлов cookie, необходимых для работы сайта, а также для анализа использования сайта и улучшения предоставляемых сервисов с использованием метрической программы Яндекс.Метрика. Продолжая использовать сайт, вы даёте согласие с использованием данных технологий».
Политика конфиденциальности
|
|
|
Не контачат std::function и std::bind
|
|||
|---|---|---|---|
|
#18+
Написал такой простой код: main.cpp: Код: plaintext 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. 24. 25. 26. 27. 28. 29. 30. 31. 32. 33. 34. 35. 36. 37. 38. 39. 40. 41. 42. 43. 44. 45. 46. 47. 48. 49. 50. 51. 52. 53. 54. авторошибка: conversion from ‘std::_Bind_helper<false, void (*)({anonymous}::MyClass<int>&&, std::__cxx11::basic_string<char>&), {anonymous}::MyClass<int, false>, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >&>::type {aka std::_Bind<void (*({anonymous}::MyClass<int>, std::__cxx11::basic_string<char>))({anonymous}::MyClass<int>&&, std::__cxx11::basic_string<char>&)>}’ to non-scalar type ‘std::function<void()>’ requested std::function<void(void)> Bind = std::bind(&Write<Type, NeedLock>, std::move(foo), Data); ^~~~ В чем проблема? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 03.06.2018, 16:55 |
|
||
|
Не контачат std::function и std::bind
|
|||
|---|---|---|---|
|
#18+
AlekseySQL, Наверно bind не умеет передавать rv-ссылки && как есть, и где-то внутри заменяет их на & или вообще на копии объекта. Замените && на &, а std::move в строке с bind на std::ref. (И для Data тоже надо std::ref, кстати, либо убрать ссылку из типа аргумента) Типа этого: Код: plaintext 1. А если вам надо именно перемещать foo то используте shared_ptr PS. Думаю что и с rv-ссылками можно извратиться и придумать как, но зачем... ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 03.06.2018, 18:14 |
|
||
|
Не контачат std::function и std::bind
|
|||
|---|---|---|---|
|
#18+
Anatoly MoskovskyAlekseySQL, Наверно bind не умеет передавать rv-ссылки && как есть, и где-то внутри заменяет их на & или вообще на копии объекта. Замените && на &, а std::move в строке с bind на std::ref. (И для Data тоже надо std::ref, кстати, либо убрать ссылку из типа аргумента) Типа этого: Код: plaintext 1. А если вам надо именно перемещать foo то используте shared_ptr PS. Думаю что и с rv-ссылками можно извратиться и придумать как, но зачем... Документация говорит другое: авторАргументы для связывания будут скопированы или перемещены, и никогда не передаются по ссылке, если только не завернуты в std::ref или std::cref. К тому же у меня уже есть рабочий код, в котором bind принимает перемещенный unique_ptr (я им обернул iostream, чтобы при возникновении исключения файл корректно закрылся). ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 03.06.2018, 18:27 |
|
||
|
Не контачат std::function и std::bind
|
|||
|---|---|---|---|
|
#18+
AlekseySQLAnatoly MoskovskyAlekseySQL, Наверно bind не умеет передавать rv-ссылки && как есть, и где-то внутри заменяет их на & или вообще на копии объекта. Замените && на &, а std::move в строке с bind на std::ref. (И для Data тоже надо std::ref, кстати, либо убрать ссылку из типа аргумента) Типа этого: Код: plaintext 1. А если вам надо именно перемещать foo то используте shared_ptr PS. Думаю что и с rv-ссылками можно извратиться и придумать как, но зачем... Документация говорит другое: авторАргументы для связывания будут скопированы или перемещены, и никогда не передаются по ссылке, если только не завернуты в std::ref или std::cref. К тому же у меня уже есть рабочий код, в котором bind принимает перемещенный unique_ptr (я им обернул iostream, чтобы при возникновении исключения файл корректно закрылся). bind обьект может вызываться больше одного раза. Поэтому передача ему rv аргумента бессмысленна. Потому он их и не берёт. Ты можешь сконструировать bind обьект с rv аргументом но не сможешь его исполнить по причине описанной в первом предложении. В твоём "работающем" коде нет исполнения bind обьекта с rv аргументом. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 04.06.2018, 10:19 |
|
||
|
Не контачат std::function и std::bind
|
|||
|---|---|---|---|
|
#18+
Anatoly Moskovsky, К сожалению, использовать ссылки не получится: у меня происходит итерация по циклу с многократным заполнением / освобождением вспомогательного массива, который через бинды передается для асинхронной записи на диск. Если я передам ссылку на обертку массива, то перейдя к записям нового клиента я очищу массив и заполню его новыми данными, т.е. по этой ссылке будут лежать уже другие записи... Так что нужно либо передавать по значению (что очень плохо при работе с массивами), либо перемещать... ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 04.06.2018, 10:20 |
|
||
|
Не контачат std::function и std::bind
|
|||
|---|---|---|---|
|
#18+
OoCcbind обьект может вызываться больше одного раза. Поэтому передача ему rv аргумента бессмысленна. Потому он их и не берёт. Ты можешь сконструировать bind обьект с rv аргументом но не сможешь его исполнить по причине описанной в первом предложении. В твоём "работающем" коде нет исполнения bind обьекта с rv аргументом. Возможно вы правы. Заглянул в свой "работающий" код: Код: plaintext 1. 2. 3. 4. 5. 6. Другими словами из unique_ptr я выдергивал сырой указатель и функцию удаления объекта и именно их сохранял в бинде. Так сказать, "раздербанивал" unique_ptr для его помещения в бинд. Хотя мне этот подход кажется неправильным: программист для того и нужен, чтобы следить за логикой работы, и если появится ошибка повторного перемещения объекта, то за разбирательства в таких ошибках он и получает свой хлеб. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 04.06.2018, 10:39 |
|
||
|
Не контачат std::function и std::bind
|
|||
|---|---|---|---|
|
#18+
Короче, я запутался в двух деревьях: надо сначала переместить свой массив в функцию (принимая НЕ по правой ссылке), а при создании bind запихнуть либо по значению (поскольку мой объект хранит указатель на выделенную память и весит очень мало), либо использовать cref. Я упростил предыдущий вариант, убрав шаблоны: Код: plaintext 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. 24. 25. 26. 27. 28. 29. 30. 31. 32. 33. 34. 35. 36. 37. 38. 39. 40. 41. 42. 43. 44. 45. 46. 47. 48. 49. 50. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 04.06.2018, 11:01 |
|
||
|
Не контачат std::function и std::bind
|
|||
|---|---|---|---|
|
#18+
Продолжу свой диалог :) В последнем примере допущена логическая ошибка: когда я выхожу из функции BigWrite, то локальная переменная foo уничтожается, и следовательно в bind- е лежит ссылка на мусор. Конечно, в приведенном примере bind до выхода из функции вызывает оператор () и ошибки вроде как нет, но если он будет использоваться для асинхронного выполнения действий (и класться в какую- нибудь коллекцию для последующего выполнения), то подобный подход не сработает. Поэтому в bind надо класть само значение, а не ссылку (не зря разработчики в bind все принимают по значению). ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 06.06.2018, 09:55 |
|
||
|
Не контачат std::function и std::bind
|
|||
|---|---|---|---|
|
#18+
Переделал для сохранения в bind-е самого значения, но получаю ошибку (MyClass не изменен): Код: plaintext 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. 24. 25. 26. 27. 28. 29. 30. 31. 32. 33. 34. 35. 36. 37. 38. 39. 40. 41. 42. 43. 44. 45. 46. 47. 48. автор/usr/include/c++/7/functional:534: ошибка: no matching function for call to ‘std::tuple<{anonymous}::MyClass>::tuple({anonymous}::MyClass&)’ : _M_f(std::move(__f)), _M_bound_args(std::forward<_Args>(__args)...) ^ Как лечить? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 06.06.2018, 10:24 |
|
||
|
Не контачат std::function и std::bind
|
|||
|---|---|---|---|
|
#18+
Выяснил, что проблема в отсутствии конструктора копирования :) Надо так: Код: plaintext 1. Но меня все- таки гложат сомнения: неужели никак нельзя в bind переместить объект? Неужели обязательно создавать копию? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 06.06.2018, 13:28 |
|
||
|
Не контачат std::function и std::bind
|
|||
|---|---|---|---|
|
#18+
AlekseySQLНо меня все- таки гложат сомнения: неужели никак нельзя в bind переместить объект? Неужели обязательно создавать копию? Начиная с C++14 можно. Но не через bind, а через лямбду. Код: plaintext 1. 2. 3. Полученный объект будет movable Гуглите "Generalized lambda capture". PS. В C++11 тоже можно извратиться в большинстве случаев. Для этого надо написать обертку которая реализует семантику перемещения в конструкторе копирования. Но тут конечно надо аккуратно )) ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 06.06.2018, 13:51 |
|
||
|
Не контачат std::function и std::bind
|
|||
|---|---|---|---|
|
#18+
Anatoly Moskovsky, спасибо! ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 06.06.2018, 14:49 |
|
||
|
Не контачат std::function и std::bind
|
|||
|---|---|---|---|
|
#18+
OoCcbind обьект может вызываться больше одного раза. Поэтому передача ему rv аргумента бессмысленна. Потому он их и не берёт. Ты можешь сконструировать bind обьект с rv аргументом но не сможешь его исполнить по причине описанной в первом предложении У Скота Майерса ("Эффективный и современный С++") на 232 странице он в примере перемещает данные в bind, а в последнем абзаце говорится, что при этом в bind создается lvalue- копия перемещенного объекта, которую можно использовать многократно. Короче, я так и не понял почему везде написано, что в bind перемещать можно, а по факту- ошибка. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 13.06.2018, 09:19 |
|
||
|
Не контачат std::function и std::bind
|
|||
|---|---|---|---|
|
#18+
AlekseySQL, А ещё Мейерс советует не пользоваться bind'ом, отдавая предпочтение лямбдам. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 13.06.2018, 12:01 |
|
||
|
Не контачат std::function и std::bind
|
|||
|---|---|---|---|
|
#18+
AlekseySQLв последнем абзаце говорится, что при этом в bind создается lvalue- копия перемещенного объекта, которую можно использовать многократно. Короче, я так и не понял почему везде написано, что в bind перемещать можно, а по факту- ошибка. lvalue- копия возможна только если у вас разрешено копирование )) ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 13.06.2018, 16:55 |
|
||
|
Не контачат std::function и std::bind
|
|||
|---|---|---|---|
|
#18+
Точнее bind вы сделаете, но скопировать его куда-то не сможете. Но вызвать не копируя сможете. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 13.06.2018, 16:59 |
|
||
|
Не контачат std::function и std::bind
|
|||
|---|---|---|---|
|
#18+
Anatoly MoskovskyТочнее bind вы сделаете, но скопировать его куда-то не сможете. Но вызвать не копируя сможете. Спасибо, за помощь в поисках. Но ошибка вылазит на строчке создания bind. В последующем (ниже по коду) я этот бинд с помощью std::move перемещаю в очередь для асинхронного выполнения отдельным потоком (не копирую, а именно перемещаю). Так что вроде ваша мысль мимо цели. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 13.06.2018, 19:10 |
|
||
|
Не контачат std::function и std::bind
|
|||
|---|---|---|---|
|
#18+
AlekseySQL, Потому что тут копирование: Код: plaintext 1. А вот ту нет: Код: plaintext 1. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 13.06.2018, 19:48 |
|
||
|
Не контачат std::function и std::bind
|
|||
|---|---|---|---|
|
#18+
Опечаточка была. А вот тут нет: Код: plaintext 1. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 13.06.2018, 19:49 |
|
||
|
Не контачат std::function и std::bind
|
|||
|---|---|---|---|
|
#18+
Последняя попытка А вот тут нет: Код: plaintext 1. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 13.06.2018, 19:50 |
|
||
|
Не контачат std::function и std::bind
|
|||
|---|---|---|---|
|
#18+
Anatoly Moskovsky, а можно подробнее, почему тут есть копирование: Код: plaintext 1. , а тут нет ???: Код: plaintext 1. Если бы спецификатор auto мог содержать в себе знак ссылки или временной ссылки, то я бы понял, но ведь он содержит только тип... Совсем не понятно. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 15.06.2018, 09:10 |
|
||
|
Не контачат std::function и std::bind
|
|||
|---|---|---|---|
|
#18+
Решил выяснить какие же функции вызываются и написал: Код: plaintext 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. 24. 25. 26. 27. 28. 29. 30. 31. 32. 33. 34. 35. 36. 37. 38. 39. 40. 41. 42. 43. 44. 45. 46. 47. 48. 49. 50. 51. 52. 53. 54. 55. 56. 57. 58. 59. 60. 61. 62. 63. 64. 65. 66. 67. 68. 69. Почему спецификатор auto так меняет положение вещей? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 15.06.2018, 10:05 |
|
||
|
Не контачат std::function и std::bind
|
|||
|---|---|---|---|
|
#18+
Решил продолжить эксперименты и получил еще более адов вывод: Код: plaintext 1. 2. 3. 4. 5. 6. 7. В первой строчке вызывается деструктор (!!!), и если после этой строки написать Bind(), то в функции Write вместо наполненного объекта foo, мы получаем пустой объект... Похоже разобраться cо странным объектом bind не получится и надо просто уходить на лямбды ... ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 15.06.2018, 10:49 |
|
||
|
Не контачат std::function и std::bind
|
|||
|---|---|---|---|
|
#18+
А вот лямбда- функции работают хорошо (у меня есть пул задач, у которых есть поле std::function<void(void)>): Код: plaintext 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. Код: plaintext 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. Видно, что если Bind объявлять с помощью std::function<void(void)>, то количество перемещений сокращается. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 15.06.2018, 12:56 |
|
||
|
|

start [/forum/topic.php?fid=57&fpage=18&tid=2017831]: |
0ms |
get settings: |
10ms |
get forum list: |
11ms |
check forum access: |
3ms |
check topic access: |
3ms |
track hit: |
56ms |
get topic data: |
11ms |
get forum data: |
2ms |
get page messages: |
56ms |
get tp. blocked users: |
1ms |
| others: | 296ms |
| total: | 449ms |

| 0 / 0 |
