powered by simpleCommunicator - 2.0.59     © 2025 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / C++ [игнор отключен] [закрыт для гостей] / [C++0x] std::for_each iterate over std::vector< std::shared_ptr< Foo > >
10 сообщений из 10, страница 1 из 1
[C++0x] std::for_each iterate over std::vector< std::shared_ptr< Foo > >
    #38678999
Фотография NekZ
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Доброго времени суток.

Начну с того, что я упоролся мне нужно вызвать определённый метод у объектов, указатели которых хранятся в shared_ptr'ах, объекты которых хранятся в std::vector. Столкнулся с проблемой компиляции, ловя вырвиглазные шаблонные сообщения об ошибках от GCC 4.9 при компиляции такого кода:

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
// упрощённый код

class Context {
   ...
}

class Node {
public:
   void render( std::ostream & stream, Context * context ) {
    ...
   }  
}

int main() {
   using namespace std::placeholders;
   std::vector< std::shared_ptr< Node > > m_nodes;
   std::ostream & stream = ...;
   Context * context = ...;
   ...
   std::for_each( m_nodes.begin(), m_nodes.end(), 
      std::bind( &Node::render, std::bind( &std::shared_ptr< Node >::get, _1 ), _1
         std::ref( stream ), context );
}



Скажу сразу, что проблема не в последней строчке.
Нужно как-то завернуть то, что вернёт std::shared_ptr< Node >::get в вызов Node::render как первый аргумент, раз это member_function. Как же это сделать?
Опыта работы с boost::bind не особо-то много, как и с std::bind.
...
Рейтинг: 0 / 0
[C++0x] std::for_each iterate over std::vector< std::shared_ptr< Foo > >
    #38679023
Фотография Anatoly Moskovsky
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
NekZ,

Вам вообще не надо трогать метод get из смартуказателя.
У смартуказателей автоматически вызываются методы вложенного класса.
Два уровня bind тут также не нужны.

Надо только правильно привязать метод с помощью bind.

Так как метод render имеет неявный аргумент this то его нужно считать первым аргументом в bind, а остальные аргументы сразу привязать.

Код: plaintext
1.
2.
std::for_each( m_nodes.begin(), m_nodes.end(),  
	std::bind(&Node::render, _1, std::ref( stream ), context)) ;
...
Рейтинг: 0 / 0
[C++0x] std::for_each iterate over std::vector< std::shared_ptr< Foo > >
    #38679026
Фотография Anatoly Moskovsky
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
А вообще конечно, вот эти for_each - извращение.
Пишите проще и к вам потянутся люди.

Код: plaintext
1.
2.
for (auto n: m_nodes) 
	n->render(stream, context);
...
Рейтинг: 0 / 0
[C++0x] std::for_each iterate over std::vector< std::shared_ptr< Foo > >
    #38679030
Фотография Anatoly Moskovsky
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Да, и забыл добавить, что уже много лет как никто не говорит C++0x
Давно уже С++11
...
Рейтинг: 0 / 0
[C++0x] std::for_each iterate over std::vector< std::shared_ptr< Foo > >
    #38679063
smald
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
NekZ

for_each реализован так

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
template<class InputIterator, class Function>
  Function for_each(InputIterator first, InputIterator last, Function fn)
{
  while (first!=last) {
    fn (*first);
    ++first;
  }
  return fn; 
}



В обработчик for_each, будет передаваться *std::vector< std::shared_ptr< Node > >::iterator, то есть std::shared_ptr< Node >.
А это приведёт к созданию каждый раз нового std::shared_ptr< Node >, конструктором копирования и его уничтожении.
при выходе. А это будет приводить к атомарным операциям с счётчиком этих std::shared_ptr< Node >. Оно надо?
Крутите цикл по старинке.

Код: plaintext
1.
2.
auto it=m_nodes.begin();
while(it!=m_nodes.end()){ (*it++)->render( std::ref( stream ), context ) ; };



И вообще в контейнеры помещают unique_ptr, так быстрее.
...
Рейтинг: 0 / 0
[C++0x] std::for_each iterate over std::vector< std::shared_ptr< Foo > >
    #38679083
Фотография Anatoly Moskovsky
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
smaldВ обработчик for_each, будет передаваться *std::vector< std::shared_ptr< Node > >::iterator, то есть std::shared_ptr< Node >.
А это приведёт к созданию каждый раз нового std::shared_ptr< Node >, конструктором копирования и его уничтожении.
Данное утверждение ложно.

Дело в том что когда в коде
Код: plaintext
1.
fn (*first)

, fn это bind на основе метода, то ничего никуда не копируется, а весь код инлайнится в такую конструкцию:
Код: plaintext
1.
((*first)->*method_ptr)(arg1, arg2)


которая в свою очередь разворачивается в такую:
Код: plaintext
1.
(first->get()->*method_ptr)(arg1, arg2)



Как видим никакого копирования смартуказателя не происходит.
...
Рейтинг: 0 / 0
[C++0x] std::for_each iterate over std::vector< std::shared_ptr< Foo > >
    #38679085
Фотография Anatoly Moskovsky
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
А вот в этом коде, да, копируется

Код: plaintext
1.
for (auto n: m_nodes)



Поэтому если важна скорость, то делается так

Код: plaintext
1.
for (auto& n: m_nodes)
...
Рейтинг: 0 / 0
[C++0x] std::for_each iterate over std::vector< std::shared_ptr< Foo > >
    #38679118
smald
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Anatoly MoskovskyДанное утверждение ложно.


Да знаем мы.

ТС надо вообще так, если хочется с bind-ом.

Код: plaintext
1.
std::for_each( m_nodes.begin(), m_nodes.end(),  std::bind( &Node::render, _1, stream, context))
...
Рейтинг: 0 / 0
[C++0x] std::for_each iterate over std::vector< std::shared_ptr< Foo > >
    #38679119
smald
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
И не забыть про
Код: plaintext
1.
using namespace std::placeholders;
...
Рейтинг: 0 / 0
[C++0x] std::for_each iterate over std::vector< std::shared_ptr< Foo > >
    #38679144
Фотография Anatoly Moskovsky
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
smald,

Чукча, оказывается, не читатель
...
Рейтинг: 0 / 0
10 сообщений из 10, страница 1 из 1
Форумы / C++ [игнор отключен] [закрыт для гостей] / [C++0x] std::for_each iterate over std::vector< std::shared_ptr< Foo > >
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]