Dem*_*unt 0 c++ templates move-semantics
我有一些信号原型类
#include <map>
#include <string>
#include <functional>
template <class T>
class Signal
{
public:
std::function<T> slot;
};
Run Code Online (Sandbox Code Playgroud)
接下来是模板单例SignalCollection类,该类自动为Signal
template <class T>
class SignalCollection
{
private:
SignalCollection() {}
SignalCollection(const SignalCollection&) = delete;
SignalCollection& operator= (const SignalCollection&) = delete;
public:
static SignalCollection& Instance()
{
static SignalCollection br{};
return br;
}
std::map<std::string, T> signals_map;
void add(T&& signal)
{
this->signals_map.insert(std::make_pair("a", std::forward<T>(signal)));
}
};
Run Code Online (Sandbox Code Playgroud)
最后,我有一个函数可以推断SignalCollection某些类型Signal
template<class T>
auto& get_collection_for_signal(T&& t)
{
return SignalCollection<T>::Instance();
}
Run Code Online (Sandbox Code Playgroud)
问题是,我无法将值添加到集合图。这是主要的:
void foo()
{
}
void main()
{
Signal<void()> sgl = Signal<void()>{}; //Create signal
sgl.slot = foo; //add slot
auto& t = get_collection_for_signal(sgl); //Get collection for this signal which is SignalCollection<Signal<void()>>
t.add(sgl); //error 1
t.signals_map["a"] = sgl; //error 2
}
Run Code Online (Sandbox Code Playgroud)
这里的问题是
template<class T>
auto& get_collection_for_signal(T&& t)
{
return SignalCollection<T>::Instance();
}
Run Code Online (Sandbox Code Playgroud)
当你这样称呼它时
auto& t = get_collection_for_signal(sgl);
Run Code Online (Sandbox Code Playgroud)
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();
}
Run Code Online (Sandbox Code Playgroud)
从中删除了cv资格和参考T(C ++ 20给了我们,std::remove_cvref因此可以使用单个帮助程序完成)。
您也可以通过以下方式获得相同的行为
template<class T>
auto& get_collection_for_signal(T)
{
return SignalCollection<T>::Instance();
}
Run Code Online (Sandbox Code Playgroud)
由于顶级简历的资格被剥夺了,而且永远不会推论出参考,因此这涉及到很多打字工作,并且给您相同的行为。
您的功能也有问题add。
void add(T&& signal)
{
this->signals_map.insert(std::make_pair("a", std::forward<T>(signal)));
}
Run Code Online (Sandbox Code Playgroud)
不使用转发引用,因为它T是类类型的一部分。您需要使其具有自己的模板才能具有转发参考。您可以通过将其更改为
template<typename U>
void add(U&& signal)
{
this->signals_map.insert(std::make_pair("a", std::forward<U>(signal)));
}
Run Code Online (Sandbox Code Playgroud)
最后
void main()
Run Code Online (Sandbox Code Playgroud)
是总是错的。 main()被要求返回一个int。通读main()在C和C ++中应该返回什么?想要查询更多的信息。