tags:

views:

88

answers:

3

Hi,

This cites for_each as follows:

  template<class InputIterator, class Function>
  Function for_each(InputIterator first, InputIterator last, Function f);

I have a collection std::list<std::string>, and a function void Do(std::string) works fine when given to for_each along with the iterators. But if I supply a function like void Do(std::string&), it does not compile. Is there a way around it? Or should I forget about it as some RVO like magic is going on? :D

EDIT:

bool PluginLoader::LoadSharedObjects()                              
{                                                                   
    for_each(l_FileNames.begin(), l_FileNames.end(), bind1st(mem_fun(&PluginLoader::LoadSharedObject),this));                                                                      
}   

void PluginLoader::LoadSharedObject(const std::string sFileName)   
{                                                                   
    void* pHandle = dlopen(sFileName.c_str(), i_LibMode);           
    //if(pHandle == NULL)
    //Check dlerror

    //Add handle to list
} 

Code added. I woul like LoadSharedObject function to be of the form void PluginLoader::LoadSharedObject(const std::string& sFileName) if it is possible.

A: 

The current standard isn't clear whether such usage of for_each should be allowed or not, and different implementations behave differently - some accept that but some not. That was considered unfortunate by some people, so C++0x is going to fix the situation by explicitly allowing mutating operations passed to for_each if the iterator is modifiable.

On the EDIT: const references aren't a problem. What errors do you get?

usta
When is this illusive C++0x going to come out. I keep seeing it everywhere these days. :D
nakiya
I can't wait for it myself :D I really hope it happens on March 2011. Quoting from http://www2.research.att.com/~bs/C++0xFAQ.html#when-standard : "The new standard is likely to be called C++11, but even a minor bureacratic delay could make that C++12."
usta
C++ is really convoluted isn't it? :D
nakiya
By no means trivial for sure :D
usta
+3  A: 

The error is not with for_each but with bind1st and mem_fun. They simply dont't support what you're trying to do. They cannot handle functions which take reference parameters. You could write your own functor, use boost::bind or wait until you're able to use C++0x lambdas.

Example for your own functor:

struct LoadSharedObjFunctor
{
    PluginLoader *pl;
public:
    explicit(PluginLoader *p)
    : pl(p) {}

    void operator()(std::string const& cref) const
    { return pl->LoadSharedObject(cref); }
};

...
std::for_each(...,...,LoadSharedObjFunctor(this));
...

Of course, you don't have to use std::for_each. A simple for-loop will do as well.

sellibitze
I can't use any third party libraries.:(. I don't think writing one of my own would turn up well :).
nakiya
@nakiya: Then write your own functor.
sellibitze
+1  A: 

If you are allowed to use boost, then what you want is boost:::bind.

#include <boost/bind.hpp>
...
for_each(l_FileNames.begin(),
         l_FileNames.end(),
         boost::bind(&PluginLoader::LoadSharedObject, this, _1)); 

Just for fun, here is why what you are trying doesn't work:

This mem_fun(&PluginLoader::LoadSharedObject) creates an object of type mem_fun1_t<void, PluginLoader, const string &>.

So bind1st(mem_fun(&PluginLoader::LoadSharedObject),this) creates an object of type binder1st< mem_fun1_t<void, PluginLoader, const string &> >.

The problem is that binder1st defines a function that looks like: ResultType operator()(const ArgType &), where ArgType is const string &. So effectively it means you are trying to form a reference to a reference.

alanwj