c++ - 为什么 std::bind 接受比绑定(bind)函数更多的参数?

标签 c++ c++11 compiler-errors

我有兴趣了解更多关于 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 values w_1, w_2, ... w_N, where N has the value 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);
}

关于c++ - 为什么 std::bind 接受比绑定(bind)函数更多的参数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56246569/

相关文章:

c++ - 创建抽象包装迭代器

c++ - 将 Boost::Beast 用于 CPU 密集型 REST API,我应该使用异步还是同步方式来实现它们以获得更好的延迟?

java - 运行我的第一个 Java 应用程序时出现 InvalidModuleDescriptorException

c++ - 编译 C++ : undefined reference

c++ - 通过接受原始数组引用的 constexpr 构造函数初始化 constexpr 变量时的 MSVC 错误?

c++ - 对自定义 C++ 库的 undefined reference

c++ - 是否可以构建一个匹配 3 个或更多非连续 UTF 代码点的 PCRE UTF-8 正则表达式

c++ - 带有反向迭代器的 std::vector 上的 std::lower_bound 产生错误的结果

c++ - "type"可以在 C++ 中传递吗?

c++ - 将 std::atomic_flag 与工作线程一起使用时出现问题