我有兴趣了解更多关于 std::bind()
与成员函数的行为,并认为 MSVC 编译以下代码很奇怪,而我尝试过的其他编译器都不会。 MSVC 编译这个有错吗?
我在编译器资源管理器中尝试了 GCC、CLang 和其他一些小编译器与 MSVC 并排:https://godbolt.org/z/DNtP-o
只有 MSVC 会编译这个:
#include <functional>
struct S{
void f(int){}
};
int main(){
S s;
auto binding = std::bind(&S::f,s, 5,3);
return 0;
}
这些是我使用“x86-64 clang 8.0.0”编译时遇到的错误:
error: static_assert failed due to requirement 'integral_constant<bool, false>::value ? sizeof...(_BoundArgs) >= integral_constant<unsigned long, 1>::value + 1 : sizeof...(_BoundArgs) == integral_constant<unsigned long, 1>::value + 1' "Wrong number of arguments for pointer-to-member"
error: no matching function for call to 'bind'
最佳答案
这里没有一个编译器是错误的,因为程序有未定义的行为。
请注意,如果您实际尝试调用绑定(bind)仿函数,MSVC 当然会出错。所以这个问题是相当学术的,因为在一个真实的程序中使用 std::bind
来创建一些永远不能在任何代码路径上调用的东西并不是很有用。
C++17 [func.bind.bind]/2说:
Requires: ... INVOKE
(fd, w_1, w_2, ..., w_N)
shall be a valid expression for some valuesw_1
,w_2
, ...w_N
, whereN
has the valuesizeof...(bound_args)
. ...
但这是对使用标准库的代码的要求,而不是对实现(编译器和/或库)的要求,而且没有说实现必须诊断违规。除非另有说明,否则违反 Requires: 段落是未定义的行为。
因此,g++ 和 clang++(当使用 libstdc++ 时)在 std::bind
调用中注意到问题的能力只是实现奖励功能的一个很好的质量。
大概 libstdc++ 通过在指向(成员)函数的指针上进行模板匹配来做到这一点。但在更一般的情况下,确定是否有任何方法可以调用具有给定数量的通配符类型参数的仿函数更加困难或不可能。所有三个编译器都接受 this code没有错误或警告:
#include <functional>
struct X {
void operator()() const;
void operator()(int) const;
};
void f() {
auto func = std::bind(X{}, 2, 3, 4);
static_cast<void>(func);
}
关于c++ - 为什么 std::bind 接受比绑定(bind)函数更多的参数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56246569/