Я работаю над библиотекой Event и сталкиваюсь с проблемой с шаблонами Variadic.
Все работает очень хорошо, за исключением того, что я не могу передавать ссылки в качестве параметров...
Вот очень упрощенный пример, написанный, чтобы разоблачить мою проблему.
struct DelayedSignal
{
~DelayedSignal ()
{ std::cout << "~DelayedSignal CLOSE" << std::endl; }
template<class C, class... Args>
DelayedSignal ( void(C::*func)(Args...), C& obj )
{ std::cout << "DelayedSignal INIT - 03 - pointer to method & pointer to class instance (Arg num: " << sizeof...(Args) << ")" << std::endl; }
template<class C, class... Args>
DelayedSignal ( void(C::*func)(Args...), C& obj, Args... args )
{
std::cout << "DelayedSignal INIT - 04 - pointer to method & pointer to class instance & arguments (Arg num: " << sizeof...(Args) << ")" << std::endl;
}
};
template<class... ArgsBis>
struct DelayedSignal_DebugHelper
{
~DelayedSignal_DebugHelper ()
{ std::cout << "~DelayedSignal_DebugHelper CLOSE" << std::endl; }
template<class C, class... Args>
DelayedSignal_DebugHelper ( void(C::*func)(Args...), C& obj )
{ std::cout << "DelayedSignal_DebugHelper INIT - 03 - pointer to method & pointer to class instance (Arg num: " << sizeof...(Args) << ")" << std::endl; }
template<class C, class... Args>
DelayedSignal_DebugHelper ( void(C::*func)(Args...), C& obj, ArgsBis... args ) // Need to use ArgsBis instead of Args to make it work
{
std::cout << "DelayedSignal_DebugHelper INIT - 04 - pointer to method & pointer to class instance & arguments (Arg num: " << sizeof...(Args) << ")" << std::endl;
}
};
template < class Tr, class... Args >
struct Signal
{
void fire ( Args... args ) { std::cout << "Signal::fire::" << sizeof...(Args) << std::endl; }
};
struct Klass {};
int main()
{
std::string str1("Blop"); // Will be used as reference
Klass k; // Will be used as reference
Signal<void, Klass&> signal_01;
Signal<void, std::string&> signal_02;
std::cout << "====== DelayedSignal :: needed for production purpose ===============" << std::endl;
// OK
DelayedSignal test01(&Signal<void, std::string&>::fire, signal_02);
// HERE IS THE PROBLEM
//DelayedSignal test02(&Signal<void, std::string&>::fire, signal_02, str1);
// OK
DelayedSignal test03(&Signal<void, Klass&>::fire, signal_01);
// HERE IS THE PROBLEM
//DelayedSignal test04(&Signal<void, Klass&>::fire, signal_01, k);
std::cout << "====== DelayedSignal_DebugHelper :: used only for debug purpose ======" << std::endl;
// OK
DelayedSignal_DebugHelper<std::string&> test05(&Signal<void, std::string&>::fire, signal_02);
// OK
DelayedSignal_DebugHelper<std::string&> test06(&Signal<void, std::string&>::fire, signal_02, str1);
// OK
DelayedSignal_DebugHelper<Klass&> test07(&Signal<void, Klass&>::fire, signal_01);
// OK
DelayedSignal_DebugHelper<Klass&> test08(&Signal<void, Klass&>::fire, signal_01, k);
return 1;
}
Когда я регистрирую все экземпляры DelayedSignal в одном экземпляре std:: list, я бы хотел избежать использования шаблона в самом классе и тем самым вместо этого использовать шаблоны для конструкторов. Я мог бы также использовать чистый виртуальный класс в качестве базы для всех DelayedSignal и указать указатели на виртуальный класс в std:: list, но я думаю, что лучше всего минимизировать использование виртуальных методов, и я действительно заинтригован этой проблемой...
Как вы можете видеть в этом примере, test02 и test04 возвращают ошибки, если они активированы.
DelayedSignal_DebugHelper почти идентичен DelayedSignal, за исключением того факта, что он использует ArgsBis (аргумент шаблона класса) для последнего конструктора вместо шаблона Args (аргумент шаблона метода), иначе он не работает (как в случае с DelayedSignal). Аргус принимается в void(C::*func)(Args...)
, но не с ArgsBis... args
, то есть тот факт, что они находятся в одном объявлении конструктора.
Насколько я знаю, нет проблем без ссылок (например, DelayedSignal test04(&Signal<void, Klass>::fire, signal_01, k);
) или с несколькими параметрами (или none), если нет ссылок.
Есть ли способ решить эту проблему?
Спасибо.