我有兴趣了解有关成员函数std::bind()
的行为的更多信息,并且认为MSVC在没有其他尝试的编译器的情况下编译以下代码是很奇怪的。 MSVC编译这个错误吗?
我在MSVC中与https://godbolt.org/z/DNtP-o并排使用了GCC,CLang和其他一些次要的编译器。
只有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”进行编译时遇到的错误:
错误:由于要求'integral_constant
:: value?,导致static_assert失败? sizeof ...(_ BoundArgs)> = integer_constant <无符号长,1> :: value + 1:sizeof ...(_ BoundArgs)== integer_constant <无符号长,1> :: value + 1'“错误的参数数量指向成员的指针” 错误:调用“ bind”没有匹配功能
答案 0 :(得分:1)
这里没有一个编译器是错误的,因为该程序具有未定义的行为。
请注意,如果您实际上尝试调用绑定函子,则MSVC当然会给出错误。因此,这个问题是相当学术性的,因为在真实的程序中使用std::bind
创建永远无法在任何代码路径上调用的内容不是很有用。
C ++ 17 [func.bind.bind]/2说:
要求:... INVOKE
(fd, w_1, w_2, ..., w_N)
是某些值w_1
,w_2
,...w_N
,其中N
的值为sizeof...(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);
}