phs/sauce — pull request #3 by jstasiak (2012-12-03 09:47:38+00:00)
Title: Allow passing reference to AbstractModule in Modules::add()

Let's say you have some sort of plugin system and every plugin has function to provide main application the dependency information:

```
// plugin.cpp
class Module : public sauce::AbstractModule {
virtual void configure() {
// ...
}
};

std::shared_ptr getModule() {
return std::make_shared();
}
```

```
// app.cpp
std::shared_ptr pluginModule = plugin->getModule();
Modules modules;
modules.add(*pluginModule);
```

``getModul`` returns pointer to ``AbstractModule`` instance because I have no information about plugin's internal ``Module`` type and it's impractical to care about it. Unfortunately, with ``Modules::add`` signature like this it will fail:

```
template
Modules & add(Module module) {
module(binder);
binder.throwAnyPending();
return *this;
}
```

The reason for this is the template will match ``sauce::AbstractModule`` type (of course after my patch to make it not-really-fully-abstract) and it will ``AbstractModule::configuration`` implementation rather than polymorphic ``configure`` from plugin's ``Module`` class (unit test provided in this pull request).

One way to fix it is to change it this way (code included in this pull request):

```
Modules & add(void (*module)(Binder&)) {
module(binder);
binder.throwAnyPending();
return *this;
}

template
Modules & add(Module module) {
module(binder);
binder.throwAnyPending();
return *this;
}

Modules & add(AbstractModule& module) {
module(binder);
binder.throwAnyPending();
return *this;
}
```

This isn't, however, ideal. It could be written like this:

```
Modules & add(void (*module)(Binder&)) {
module(binder);
binder.throwAnyPending();
return *this;
}

Modules & add(AbstractModule& module) {
module(binder);
binder.throwAnyPending();
return *this;
}
```

But this version will fail some tests because C++ doesn't allow passing temporary values as by reference (example: ``Modules().add(Module1()).add(Module2())``)

If you used C++11 for this project (which, as far as I can tell, you don't), it could be written like this:

```
Modules & add(void (*module)(Binder&)) {
module(binder);
binder.throwAnyPending();
return *this;
}

Modules & add(AbstractModule&& module) {
module(binder);
binder.throwAnyPending();
return *this;
}
```

rvalue reference here allows us to pass temporary values there.