samedi 20 décembre 2014

Deduce types pack from a variadic-templated class and declare an argument of the same types pack

First off, sorry for unclear question title, feel free to edit if you think of a better way to state it.


I have a class:



template <typename ...Arguments>
class CSignal
{
template <typename ...ActualArguments>
void invoke(ActualArguments&&... args) const {}
};


And another one, this is what I have a problem with:



class SomeClass
{
template<typename ...Arguments>
void invokeQueued(CSignal<Arguments...>& signal, const Arguments&... args)
{
m_queue.emplace_back([=](){signal.invoke(args...);});
}

std::deque<std::function<void (void)>> m_queue;
};


Problem:



CSignal<float> signal;
int i = 0;
SomeClass().invokeQueued(signal, i);


Error:



template parameter 'Arguments' is ambiguous
could be 'float'
or 'int'


Possible naive solution



template<typename ...FormalArguments, typename ...ActualArguments>
void invokeQueued(CSignal<FormalArguments...>& signal, const ActualArguments&... args)
{
m_queue.emplace_back([=](){signal.invoke(args...);});
}


is not acceptable in this specific case, because I need to capture the arguments by value (copy them into the lambda), and the conversion from ActualArguments to FormalArguments must occur at the time invokeQueued is called, not when the lambda is called.


If I could typedef the arguments pack in the CSignal class, I would do:



template<typename ...FormalArguments>
void invokeQueued(CSignal<FormalArguments...>& signal, const CSignal<FormalArguments...>::argument_types&... args)
{
m_queue.emplace_back([=](){signal.invoke(args...);});
}


But it doesn't seem possible. Solutions?


Aucun commentaire:

Enregistrer un commentaire