【问题标题】:std::bind overload resolutionstd::bind 重载决议
【发布时间】:2011-05-08 18:03:12
【问题描述】:

以下代码运行良好

#include <functional>

using namespace std;
using namespace std::placeholders;

class A
{
  int operator()( int i, int j ) { return i - j; }
};

A a;
auto aBind = bind( &A::operator(), ref(a), _2, _1 );

这不是

#include <functional>

using namespace std;
using namespace std::placeholders;

class A
{
  int operator()( int i, int j ) { return i - j; }
  int operator()( int i ) { return -i; }
};

A a;
auto aBind = bind( &A::operator(), ref(a), _2, _1 );

我已经尝试过使用语法来尝试并明确地解决我想要的代码中的哪个函数到目前为止如果没有运气就无法工作。如何编写绑定行以选择采用两个整数参数的调用?

【问题讨论】:

  • A::operator() 不是指单个函数,而是指一系列函数:我认为您必须对其进行强制转换才能“选择”正确的重载。由于我不熟悉 C++0x 并且我可能不知道更优雅的解决方案,因此我不会将此作为答案进行验证。
  • 我写了an answer to a similar question,展示了三种将参数强制为正确类型的方法。

标签: c++ c++11 functional-programming std


【解决方案1】:

您需要强制转换来消除重载函数的歧义:

(int(A::*)(int,int))&A::operator()

【讨论】:

  • 我会写成static_cast&lt;int(A::*)(int,int)&gt;(&amp;A::operator()),明确表示这不是转换
  • 您应该能够简单地分配给正确类型的临时 (int(A::*method)(int,int) = &amp;A::operator();) 并使用它。就个人而言,我有一个小的up_cast() 方法:template&lt;typename T, typename U&gt; T up_cast(U value) { return value; } - 这比static_cast 更清楚地表明没有进行转换。
【解决方案2】:

如果你有可用的 C++11,你应该更喜欢 lambdas 而不是 std::bind,因为它通常会导致代码更具可读性:

auto aBind = [&a](int i, int j){ return a(i, j); };

相比

auto aBind = std::bind(static_cast<int(A::*)(int,int)>(&A::operator()), std::ref(a), std::placeholders::_2, std::placeholders::_1);

【讨论】:

  • 不仅可读性更强,而且性能更好。我记得看过一个关于它的演讲。结论是 std::bind 不允许编译器执行各种优化,但在使用 lambda 时它没有问题。
【解决方案3】:

有一些可用的“lift”宏可以自动将重载集作为参数传递,方法是将它们包装到一个简单地转发传递给它的所有参数的 lambda 中。 Boost提供的一种可以使代码编译通过

#include <boost/hof/lift.hpp>

auto aBind = bind(BOOST_HOF_LIFT(&A::operator()), ref(a), _2, _1 );

还有一些建议可以更轻松地传递重载集,参见例如P0834,但不知道这是否会找到或找到共识。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-10-15
    • 1970-01-01
    • 2020-04-07
    • 1970-01-01
    • 2016-11-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多