我正在使用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)
^~~~
答案 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<...>
。
纯粹c++11:
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代码中窒息,尽管它符合c++11。有许多替代方案,其中的工作依赖于确切的编译器。