Skip to main content
GameDev.net gamedev.net
🔒 Locked

for_each on class member

Started by Black Knight Oct 24, 2009 at 9:55 PM 9 replies 2.7k views
Original Post
Black Knight
Black Knight
So I have a vector which holds shared_ptrs the objects are derived from a base GUIElement class,I tried to use for_each to call a render method of the renderer on the objects but Im getting a compile error.Here is the code

std::vector<boost::shared_ptr<GUIPanel>> m_Panels;

//somewhere else
for_each(m_Panels.begin(),m_Panels.end(),Renderer::drawGUIElement);


Renderer::drawGUIElement takes a parameter as GUIElement is that the problem?
drakostar
drakostar
This:
#include <memory>using namespace std;void foo(auto_ptr<int> p){}int main(){    int *x = new int(42);    foo(x);    return 0;}


Dies like:
$ g++ ptest.cppptest.cpp: In function ‘int main()’:ptest.cpp:11: error: conversion from ‘int*’ to non-scalar type ‘std::auto_ptr<int>’ requested


So...yes. Smart pointers and raw pointers are not interchangeable.

You're already using Boost, so try something like:
#define foreach BOOST_FOREACHforeach(shared_ptr<GUIPanel> p, m_Panels) {    Renderer::drawGUIElement(p.get());}

Zakwayda
Zakwayda
Quote:
Renderer::drawGUIElement takes a parameter as GUIElement is that the problem?
Is the 'GUIElement' argument passed by value, reference, or pointer? (Maybe you could just post the function declaration for Renderer::drawGUIElement.)
scjohnno
scjohnno
#include <boost/bind.hpp>std::vector<boost::shared_ptr<GUIPanel>> m_Panels;Renderer r;//somewhere elsefor_each(m_Panels.begin(),m_Panels.end(),boost::bind(&Renderer::drawGUIElement, &r, _1));


There's a way to do it with just the standard library, but I honestly haven't bothered to learn how since I discovered Boost.Bind.

Edit: I'm assuming that Renderer::drawGUIElement isn't a static function. If it is, remove the '&r' argument.
Trienco
Trienco
Your way would probably work, if drawGUIElement was a static member function.

Since you're already using boost, I'd stick with bind. An alternative that isn't quite as elegant might be:

struct functor{   functor(const Renderer& renderer)      : renderer_(renderer) {}   const Renderer& renderer_;   void operator()(const shared_ptr<GUIThingy>& element)   {      renderer.drawGUIElement(element);   }};for_each(begin, end, functor(my_Renderer));


Of course, once you think about there being a pattern and making a generic template solution, a simple form of bind is probably what you come up with (with bind returning a temporary functor that does the above).
f@dzhttp://festini.device-zero.de
Zakwayda
Zakwayda
Have you tried scjohnno's code? It looks like it's probably what you're looking for.

Also, I'd probably pass the shared pointer argument by constant reference rather than by value, i.e.:
void D3D9Renderer::drawGUIElement(const boost::shared_ptr<GUIElement>& element)
phresnel
phresnel
Quote:
Original post by Black Knight
std::vector<boost::shared_ptr<GUIPanel>> m_Panels;


Small nitpick: In current C++, ">>" is not allowed to close multiple template argument lists. C++0x will solve this, but is not the standard, yet, so this is the correct one:

std::vector<boost::shared_ptr<GUIPanel> > m_Panels;
_the_phantom_
_the_phantom_
boost::shared_ptr is not the same type as boost::shared_ptr, nor is it considerd a related type iirc and as I recall shared_ptr doesn't support automatic conversion between types of T directly, however you might want to check the docs on this because if I'm recalling it correctly its pretty clear about it.
Sneftel
Sneftel
See if this works:
for(std::vector<boost::shared_ptr<GUIPanel>>::iterator ip = m_Panels.begin(); ip != m_Panels.end(); ++ip){  drawGUIElement(static_pointer_cast<GUIElement>(*ip));}

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.