我正在尝试制作一个在 std::bind 之前匹配的网络绑定函数

I'm trying to make a networking bind function which matches before std::bind

本文关键字:bind 函数 绑定 网络 std 一个      更新时间:2023-10-16

我正在C++中开发一个库,这是一个更高级别的套接字接口。 这个想法是具有相同函数名称的类似调用,但具有更干净的界面和更好的类型安全性。 这意味着我有自己的(网络)绑定函数,它的签名如下:

void MySocketLib::bind(const MySocketLib::MySocket &s, const MySocketLib::MyEndpoint &e);

其中 MySocketLib 是一个命名空间。 这一切都很好,只要你打电话

MySocketLib::bind(s,e);

当 s 和 e 具有匹配的类型时。 但是,如果你做这样的事情:

#include <functional>
#include "mysocketlib.h"
using namespace std;
using namespace MySocketLib;
...
bind(s,e);

然后,绑定在功能中选取 std::bind 。 我总是可以只调用MySocketLib::bind(s,e),但我更喜欢非限定调用选择MySocketLib::binb函数而不是std::bind模板。 这是使用 gnu g++。

std::bind 和 ::bind 之间的类似问题似乎已在 gcc 标头中得到解决。 但它不能解决我的问题,因为我的套接字不是整数。

我尝试的是创建一个专业化,如下所示:

namespace std {
template<>
void bind(const MySocketLib::MySocket &s, const MySocketLib::MyEndpoint &e) {
MySocketLib::bind(s,a);
} }

但它告诉我我的 bind(...) 与任何模板声明都不匹配。 (完整的编译器消息如下)。 即使这些是它愉快地实例化 std::bind 的调用中的确切类型。 我想要的是一些关于我到底如何专注于 std::bind 的建议,或者其他一些方法来完成使普通 bind() 在使用两个命名空间时引用 MySocketLib::bind 而不是 std::bind 的方法。

以下是 g++ 针对我失败的专业化的完整编译器诊断。 任何建议表示赞赏。

In file included from mysocketlib.cpp:12:0:
mysocketlib.h:330:6: error: template-id 'bind<>' for 'void std::bind(const MySocketLib::MySocket&, const MySocketLib::MyEndpoint&)' does not match any template declaration
void bind(const MySocketLib::MySocket &s, const MySocketLib::MyEndpoint &a) {
^~~~
In file included from mysocketlib.h:323:0,
from mysocketlib.cpp:12:
/usr/include/c++/7/functional:899:5: note: candidates are: template<class _Result, class _Func, class ... _BoundArgs> typename std::_Bindres_helper<_Result, _Func, _BoundArgs>::type std::bind(_Func&&, _BoundArgs&& ...)
bind(_Func&& __f, _BoundArgs&&... __args)
^~~~
/usr/include/c++/7/functional:875:5: note:                 template<class _Func, class ... _BoundArgs> typename std::_Bind_helper<std::__is_socketlike<_Func>::value, _Func, _BoundArgs ...>::type std::bind(_Func&&, _BoundArgs&& ...)
bind(_Func&& __f, _BoundArgs&&... __args)
^~~~

请参阅上面的评论,为什么这是在设计类似于"客户不断从我的建筑物上敲下底层,而上层则倒塌。 当底层被淘汰时,我如何确保顶层仍然屹立不倒?

std::bind是使用变量转发模板实现的。

namespace MySocketLib {
namespace details {
void my_socket_bind(const ::MySocketLib::MySocket &s, const ::MySocketLib::MyEndpoint &e);
}
template<class S0, class S1,
std::enable_if_t<
std::is_same< std::decay_t<S0>, MySocket >{}
&& std::is_same< std::decay_t<S1>, EndPoint >{}
, bool> = true
>
void bind(S0&&s, S1&e) {
return details::my_socket_bind( s, e );
}
}

这是脆弱的,神秘的,但当两者导入同一范围时,应将您的bind置于或高于任何std::bind

您实现MySocketLib::details::my_socket_bind.

在纯 c++11 中:

enable_if_t<...>可能必须替换为typename enable_if<...>::type.

is_same<...>{}可能必须替换为is_same<...>::value.

一些较旧的编译器可能会对我的SFINAE代码感到窒息,尽管它符合c ++ 11。 有许多替代方案,哪些工作取决于确切的编译器。