我试图创建一个在std :: bind之前匹配的网络绑定函数

时间:2018-01-03 07:44:17

标签: c++ c++11 g++ std bind

我正在使用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);

然后,bind在功能中获取std :: bind。我总是可以调用MySocketLib :: bind(s,e),但我更喜欢不合格的调用拾取MySocketLib :: bind函数而不是std :: bind模板。这是使用gnu g ++。

似乎在gd标头中已经解决了std :: bind和:: bind之间的similar problem问题。但它并没有解决我的问题,因为我的套接字不是整数。

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

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。 / p>

以下是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)
     ^~~~

1 个答案:

答案 0 :(得分:0)

请参阅上面的评论,为什么这是一个类似于“客户继续从我的建筑物上敲下底层,并且上层落下的解决方案”的设计解决方案。当底层被撞掉时,如何确保顶层仍然站立? “

std::bind使用varardic转发模板实现。

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

您实施enable_if_t<...>

纯粹

typename enable_if<...>::type可能必须替换为is_same<...>{}

is_same<...>::value可能必须替换为public void setChecked(boolean checked) { if (mChecked != checked) { mChecked = checked; refreshDrawableState(); notifyViewAccessibilityStateChangedIfNeeded( AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED); // Avoid infinite recursions if setChecked() is called from a listener if (mBroadcasting) { return; } mBroadcasting = true; if (mOnCheckedChangeListener != null) { mOnCheckedChangeListener.onCheckedChanged(this, mChecked); } if (mOnCheckedChangeWidgetListener != null) { mOnCheckedChangeWidgetListener.onCheckedChanged(this, mChecked); } mBroadcasting = false; } }

一些较旧的编译器可能会在我的SFINAE代码中窒息,尽管它符合。有许多替代方案,其中的工作依赖于确切的编译器。