Note: I am working with VS2013 so the C++11 features available are limited.
I am having trouble with overloading a template function depending on if the argument type is callable or not and, ideally, if the arguments match a specific pattern.
Here is a very simplified example of the code I have, my problem being how to implement update_callabe()
overloads :
template< class T, class... Args >
void update_callable( const std::vector<T>& objects, Args&&... args ); // 1: How to implement this?
template< class T, class... UpdateArgs>
class Controller
{ //...
virtual void update( T&, UpdateArgs... args ) = 0;
public:
template< class IterBegin, class IterEnd, class... Args >
void update_batch( IterBegin first, IterEnd last, Args&&... args )
{
std::for_each( first, last, [&]( T& object ){ update(object, args...); }
}
//...
};
template< class T, class... UpdateArgs >
class Group
{
public:
using ControllerType = Controller<T,UpdateArgs...>;
void add( ControllerType& controler ) { /* ... */ m_controllers.emplace_back( &controller ); }
template< class... Args >
void update( Args&&... args )
{
update_callable(m_objects, std::forward<Args>(args)); // 2
for( auto* controller : m_controllers )
{
controller->update_batch( begin(m_objects), end(m_objects), std::forward<Args>(args)); // 3
}
}
private:
std::vector<T> m_objects;
std::vector<ControllerType*> m_controllers;
//...
};
A. What I want to achieve with update_callabe()
overloads (in priority order):
- if T is callable with Args arguments, then call all T objects with the arguments.
- if T is not callable with Args arguments, then do exactly nothing.
B. That would be ok for me, but ideally I would like update_callabe()
overloads that follow these rules (in priority order):
- if T is callable with Args arguments, then call all T objects with the arguments.
- if T is callable with NO arguments, then call all T objects with no arguments.
- if T is not callable with Args arguments nor NO arguments, then do exactly nothing.
I have tried with enable_if, conditional and several advanced techniques but I'm no expert (yet) so I'm failing to express this correctly.
Some notes about the example here:
- it's a simplified example, I didn't try to compile it but it is close to my code;
- (2) basically we want to call the default update of the objects stored if the type of the objects provide one, "default update" meaning here the call operator either with arguments from the update context or with no arguments if the type don't need them;
- (3) there is a second update loop for "controller" objects that can manipulate externally the stored objects;