2

我注意到 boost::bind 与 std::bind 不同,当这些函数之一没有任何参数时,它可以使用重载函数。我对吗?这有记录吗?

#include <boost/bind.hpp>

#include <functional>
#include <iostream>

void foo()
{
    std::cout << "::foo() \n";
}

void foo(int)
{
    std::cout << "::foo(int) \n";
}

int main()
{
    boost::bind(foo)(); // Ok
    boost::bind(foo, 0)(); // Ok

    // std::bind(foo)(); // Error
    // std::bind(foo, 0)(); // Error
}

#include <boost/bind.hpp>

#include <functional>
#include <iostream>

void foo(int)
{
    std::cout << "::foo(int) \n";
}

void foo(const std::string&)
{
    std::cout << "::foo(const std::string&) \n";
}

int main()
{
    // boost::bind(foo, 0)(); // Error
    // boost::bind(foo, "str")(); // Error

    // std::bind(foo, 0)(); // Error
    // std::bind(foo, "str")(); // Error
}
4

3 回答 3

3

我认为这只是实现细节的意外产物,我不认为 Boost 提供任何关于自动解决正确重载的保证。

std::bind是使用可变参数模板实现的 C++11 功能。

boost::bind是为 C++03 实现的,这意味着它依赖于大量重载的函数模板。

两者的实现细节完全不同,因此,我认为它们的行为之间的任何差异都是由此产生的结果,而不是有意和特定的差异。

Boost 文档只说明了这一点:“尝试绑定重载函数通常会导致错误,因为无法判断要绑定哪个重载。”

在我的书中,这意味着 Boost 文档告诉您,无论这是否会工作(编译)甚至选择正确的重载,都是“未定义的行为”。

据我所知,您应该始终使用显式强制转换 ( static_cast) 来修复您希望选择的重载的签名。这对于boost::bind和都是正确的std::bind,从这个意义上说,两种实现都同意。

于 2013-10-07T06:23:27.113 回答
2

它被记录为“接口”->“概要”部分的一部分,其中列出了重载。正如你在那里看到的,Boost 不使用可变参数模板,因此当给定这些重载时,明确这些:

template<class R> unspecified-2 bind(R (*f) ());
template<class F, class A1> unspecified-3-1 bind(F f, A1 a1);
template<class R, class B1, class A1> unspecified-4 bind(R (*f) (B1), A1 a1);

编译器更喜欢带有空参数列表的重载版本而不是其他版本,因为它是更好的匹配。不过,我不认为这是故意的。

于 2013-10-07T06:30:32.437 回答
1

第一种情况在 MSVC10 中与 和 都编译得很好stdboost因为 MSVC10 不支持可变参数模板,所以std::bind实现类似于boost::bind)。

第二种情况无法编译,因为bind可以解析具有不同数量的重载,但不能解析仅因参数类型而不同的重载。

于 2013-10-07T10:37:56.350 回答