8

我需要从绑定的成员函数创建一个谓词,所以我将它包装在一个boost::function<bool(SomeObject const &)>. 这似乎很好,一切都很好,但我也需要在一种情况下否定它。然而

boost::function<bool(SomeObject const &)> pred;
std::not1(pred);

无法在 MSVC++ 9.0 (Visual Studio 2008) 下编译,抱怨对引用的引用无效:

C:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\include\functional(213) : warning C4181: qualifier applied to reference type; ignored
C:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\include\functional(213) : error C2529: '_Left' : reference to reference is illegal

问题是boost::function定义argument_typeasSomeObject const &和内部std::unary_negate<_Fn1>实例化的 bystd::not1尝试使用const typename _Fn1::argument_type&并且编译器拒绝它,因为T::argument_type它已经是一个引用。我确信它应该在 C++11 下编译,但这是旧的编译器,只有 C++03。所以我想知道是谁的错:

  • 编译器的,因为它应该折叠引用(显然不是)
  • 标准库的,因为它应该准备好处理获取引用的函子(显然不是,因为规范定义unary_negateconst typename Predicate::argument_type& x参数),
  • boost's,因为argument_type即使实际参数是 or 也不应该被引用
  • 我的,因为boost::function不应该与参考参数一起使用?
4

1 回答 1

1

问题当然不是 Boost 的;boost::function基本上只是std::function,具有所有相同的语义。带有参考参数的 s也boost::function可以正常工作。您只是不能将它们与std::not1其他<functional>东西一起使用。

C++11 的引用折叠使std::not1工作按您认为应该的方式工作。如果没有引用折叠,C++03 中指定的方式std::not1是不可能工作的——除非在实现者做了一些创造性的解释而不是盲目地遵循标准的字母。

可以通过std::not1C++03 中std::unary_negate使用引用 s 添加 for 谓词的特化argument_type,但 libc++ 和 libstdc++ 都没有这样做。

但你知道谁有吗?促进!如果您只是将代码更改为boost::not1在您当前使用的任何地方使用std::not1,那么一切都会正常工作。基本上,把boost命名空间想象成一个兼容 C++11 的std; 在 C++11 的std命名空间中工作的任何东西都可能在 C++03 的boost命名空间中工作。


警告,希望题外话:我的 Macbook ( Apple LLVM version 4.2 (clang-425.0.28) (based on LLVM 3.2svn)) 上的 Clang 编译器即使在模式下也会默默地折叠引用-std=c++03,因此

typedef const int& ref;
typedef const ref& ref2;

不会产生错误。当您测试您的 C++03 代码时,请确保您没有使用具有此错误功能的编译器。

于 2013-11-10T04:25:42.273 回答