Проблема здесь
template<class T>
auto& get_collection_for_signal(T&& t)
{
return SignalCollection<T>::Instance();
}
Когда вы называете это как
auto& t = get_collection_for_signal(sgl);
T
выводится как Signal<void()>&
, и это означает, что вы возвращаете SignalCollection<Signal<void()>&>
, что не то, что вы хотите. Что вам нужно сделать, это удалить ссылку из типа. Вы можете сделать это, используя
template<class T>
auto& get_collection_for_signal(T&&)
{
return SignalCollection<std::remove_cv_t<std::remove_reference_t<T>>>::Instance();
}
, который удалил квалификацию cv и ссылку из T
(C ++ 20 дает нам std::remove_cvref
, так что это может быть сделано с одним помощником).
Вы также можете получить то же поведение с
template<class T>
auto& get_collection_for_signal(T)
{
return SignalCollection<T>::Instance();
}
Это включает в себя намного меньше ввода и дает вам такое же поведение, так как квалификация высшего уровня cv исключается, и это никогда не выведет ссылку.
У вас также есть проблема с функцией add
.
void add(T&& signal)
{
this->signals_map.insert(std::make_pair("a", std::forward<T>(signal)));
}
не использует ссылку для пересылки, поскольку T
является частью типа класса. Вы должны сделать его собственным шаблоном, чтобы иметь ссылку для пересылки. Вы можете сделать это, изменив его на
template<typename U>
void add(U&& signal)
{
this->signals_map.insert(std::make_pair("a", std::forward<U>(signal)));
}
наконец
void main()
это всегда неправильно. main()
уполномочен вернуть int
. Прочитайте Что должна вернуть main () в C и C ++? для получения дополнительной информации.