【问题标题】:what alternative to std::not1 is to be used when using std::tr1::bind or std::tr1::mem_fn使用 std::tr1::bind 或 std::tr1::mem_fn 时,将使用什么替代 std::not1
【发布时间】:2012-05-07 14:07:38
【问题描述】:

我有一个我的类 Foo 的智能 ptr 向量:

struct Foo
{
  Foo() : mEnabled( false ) {}

  bool mEnabled;

  bool isEnabled() const { return mEnabled; }
  void setEnabled( bool inEnabled ) { mEnabled = inEnabled; }
  /* ... */
};

typedef std::tr1::shared_ptr< Foo > tFooPtr;

typedef std::vector< tFooPtr > tFooVec;

我已经很好地工作了:

 tFooVec foo_vector; // insert couple of elements
 size_t count = count_if( foo_vector.begin(), foo_vector.end(), std::tr1::mem_fn( &Foo::isEnabled ) );

但是当我想 count_if “禁用” Foo 对象时使用什么功能性“助手”

 size_t count = count_if( foo_vector.begin(), foo_vector.end(), std::not1( std::tr1::mem_fn( &Foo::isEnabled ) ) ); // does not compile

上面一行没有编译:

/usr/lib/gcc/x86_64-redhat-linux/4.1.2/../../../../include/c++/4.1.2/bits/stl_algo.h:446: error: no match for call to '(std::unary_negate<std::tr1::_Mem_fn<bool (Foo::*)()const> >) (std::tr1::shared_ptr<Foo>&)'
/usr/lib/gcc/x86_64-redhat-linux/4.1.2/../../../../include/c++/4.1.2/bits/stl_function.h:322: note: candidates are: bool std::unary_negate<_Predicate>::operator()(const typename _Predicate::argument_type&) const [with _Predicate = std::tr1::_Mem_fn<bool (Foo::*)()const>]
make: *** [src/shared_ptr_tests.o] Error 1

(在 Linux 上使用 g++ 4.1.2)

我认为编译问题来自 std::not1 使用 std::unary_negate 的事实,这需要函数/谓词提供 Predicate::argument_type 。后者在 Predicate 派生自 std::unary_function sigh

时给出

话虽如此,我假设std::tr1::mem_fn 没有使用std::unary_function,也没有提供argument_type

我现在使用的解决方案是,我现在使用 boost::bind 而不是 std::tr1::bind

#include <boost/bind.hpp>
using namespace boost;
...
size_t countboost = count_if( foo_vector.begin(), foo_vector.end(), !( bind( &Foo::isEnabled, _1 )) );

为避免复杂化(和混淆),我在整个代码中将 std::tr1::bind 的用法替换为 boost::bind。

【问题讨论】:

  • 如果您可以使用更新的编译器 (C++11),则可以使用 lambda。
  • 很想...不能 - 我的代码编译所在的系统不属于我自己。更糟糕的是,我的代码也必须在 AIX 上用 xlC 编译。所以,我坚持使用“老式”函子。
  • 荒谬的答案:size_t count = v.size() - std::count_if( v.begin(), v.end(), std::tr1::mem_fn(&amp;Foo::isEnabled));。有时最简单的答案是避免问题。
  • count_if 只是一个例子......我也在寻求应用 remove_copy_if。也许我也应该在我的例子中使用它。

标签: c++ stl functor


【解决方案1】:

!boost::bind(... 对我有用:

  bool test(int i)
  {
    return i < 2;
  }

  TEST( boost_bind_test, negateTest )
  {
    std::vector<int> vec;
    vec.push_back(1);
    vec.push_back(2);
    vec.push_back(3);

    ASSERT_EQ(2, count_if( vec.begin(), vec.end(), !boost::bind(&test, _1)));
  };

【讨论】:

  • size_t countN = count_if( foo_vector.begin(), foo_vector.end(), ! ( std::tr1::mem_fn( &Foo::isEnabled ) ) );结果:../src/shared_ptr_tests.cpp:217:错误:'operator!' 不匹配在 '!std::tr1::mem_fn [with _Tp = bool ()()const, _Class = Foo](&Foo::isEnabled)' ../src/shared_ptr_tests.cpp:217: 注意:候选人是:操作员! (bool)
  • @CarstenGreiner 您使用哪个版本的 boost?此功能已在过时的 boost 1.33 中添加。
  • 呃,伙计们——我们不是在一开始谈论 boost,而是 std::tr1——我知道 tr1 是在 boost 中实现的,但是我直接使用 boost包括。所以,是的,我已经设置了 boost 1_44,但在这里我将自己限制在 std:tr1 的东西上。 (也许我会去重新考虑使用 boost)。
  • 现在使用boost::bind,我需要添加这个模板template&lt;class T&gt; inline T * get_pointer(std::tr1::shared_ptr&lt;T&gt; const &amp; p) { return p.get(); } 后者是由于我使用std::tr1::shared_ptr(和不是 boost::shared_ptr
【解决方案2】:

根本问题是mem_fun(isEnabled) 采用const Foo *,而算法count_ifshared_ptr&lt;Foo&gt; 传递给它的谓词。

我不完全确定为什么它适用于 mem_fn( &amp;Foo::isEnabled ),但不适用于 not1(mem_fn( &amp;Foo::isEnabled ))。我能想到的是,额外的包装器需要进行不同的转换。但你可以解决它:

bool sharedEnabled(tFooPtr x) {
  return x->isEnabled();
}

size_t count2 = std::count_if( foo_vector.begin(), foo_vector.end(), std::not1( std::ptr_fun(&sharedEnabled ) ) );

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-08-08
    • 1970-01-01
    • 2011-08-01
    • 1970-01-01
    • 2012-06-11
    • 2010-10-03
    相关资源
    最近更新 更多