如何解决c ++函数多态性/模板
我的目标是提供三种调用函数 listen()
的方法。有一个更好的方法吗? (比如使用模板或默认值参数,所以我只能实现一个 listen()
函数)
我目前的方法
void listen(const int &port,const std::function<void(std::string err)> &f) {
http_server_.listen(port,[f](std::string err) { f(err); });
}
void listen(const int &port,const std::function<void()> &f) {
http_server_.listen(port,[f](std::string err) { f(); });
}
void listen(const int &port) {
http_server_.listen(port,[](std::string err) {});
}
我尝试了看起来像这样的模板方法
template <typename Func> void listen(const int &port,Func f = {}) {
// do some if-else here.
}
但它不起作用。
解决方法
IMO,您的方法接近最佳。如果我在写这个,我只会做一些小的改动:
void listen(int port,std::function<void(const std::string &err)> f)
{
http_server_.listen(port,std::move(f));
}
void listen(int port,std::function<void()> f)
{
http_server_.listen(port,[f = std::move(f)](const std::string &){f();});
}
void listen(int port)
{
// Are you sure the lambda is needed? Maybe passing `nullptr` will work.
http_server_.listen(port,[](const std::string &){});
}
这里,lambda 捕获中的 f = std::move(f)
(而不是 f
)至少需要 C++14。如果您仅限于 C++11 并且不能这样做,那么您应该将 f
改回由 const 引用传递(在第二个重载中)。
在 C++17 之前无法轻松地将这些组合成单个函数,并且需要更多的样板文件,而不是将要消除的。
在 C++17 中你可以使用 if constexpr
,但如果你问我,它仍然只会让事情变得更糟:
template <typename,typename...> struct always_false : std::false_type {};
template <typename F = std::nullptr_t>
void listen(int port,F &&f = nullptr)
{
if constexpr (std::is_nullptr_v<std::remove_const_t<std::remove_reference_t<F>>>)
{
http_server_.listen(port,[](const std::string &) {});
}
else
{
http_server_.listen(port,[f = std::forward<F>(f)](const std::string &err)
{
if constexpr (std::is_invocable_v<const F &,const std::string &>)
std::invoke(f,err);
else if constexpr (std::is_invocable_v<const F &>)
std::invoke(f);
else
static_assert(always_false<F>,"The function is invalid.");
});
}
}
这不仅需要两倍的输入,还可以防止调用者使用 SFINAE 检查您的函数接受或不接受哪些函数参数。
,void listen(int port,std::function<void(std::string err)> f) {
http_server_.listen(port,std::function<void()> f={}) {
listen(port,[f=std::move(f)](std::string err) { f(); });
}
这更干燥。在 c++20 中,您可以节省一些开销:
void listen(int port,std::invocable<std::string> auto f) {
http_server_.listen(port,std::invocable<> auto f=[]{}) {
listen(port,[f=std::move(f)](std::string const&) { f(); });
}
使用概念,但我不会打扰。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。