2012-10-05 5 views
8

Ich muss ein Prädikat aus gebundener Elementfunktion erstellen, also habe ich es in eine boost::function<bool(SomeObject const &)> eingewickelt. Das scheint in Ordnung zu sein und alles, aber ich musste es auch in einem Fall negieren. JedochReferenzkollaps unter C++ 03

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

nicht unter MSVC++ kompiliert 9.0 (Visual Studio 2008), dass der Bezug zu beschweren Referenz ist ungültig:

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 

Das Problem ist, dass boost::function die argument_type als SomeObject const & definiert und die std::unary_negate<_Fn1> instanziiert durch std::not1 intern versucht, const typename _Fn1::argument_type& zu verwenden, und Compiler weist es zurück, weil T::argument_type bereits eine Referenz ist. Ich bin mir sicher, dass das unter C++ 11 kompiliert werden sollte, aber das ist ein alter Compiler, der nur C++ 03 ist. So würde Ich mag wissen, wer schuld ist:

  • die Compiler, weil sie den Verweis kollabieren sollte (apparently not),
  • die Standard-Bibliothek, weil sie bereit sein sollte, functors unter Referenzen zu handhaben (anscheinend nicht, weil die Spezifikation definiert mit const typename Predicate::argument_type& x Argumente unary_negate),
  • Auftrieb des, weil argument_type nicht Bezug auch sein soll, wenn das tatsächliche Argument ist oder
  • Mine, weil boost::function sollte nicht mit Bezug Argumenten verwendet werden?
+0

Kompiliert es unter anderen Compilern? – eh9

+0

@ eh9: Mit gcc kompiliert es, zumindest für mingw32 und cygwin Ziele. –

+0

@ eh9: Aber es ist nicht relevant für die Frage; Wer ist schuld, es ist und warum hängt von der Spezifikation ab. –

Antwort

1

Der Fehler ist sicherlich nicht Boost; boost::function ist im Grunde nur std::function, mit der gleichen Semantik. Und boost::function s mit Referenzparametern funktionieren auch gut. Sie können sie einfach nicht mit std::not1 oder dem Rest der <functional> Sachen verwenden.

C++ 11s Referenz-Kollabieren macht std::not1 funktioniert so, wie Sie denken, dass es sollte. Die Art und Weise, wie in C++ 03 std::not1 angegeben wurde, könnte ohne Referenz-Kollaps nicht funktionieren - außer in Implementierungen, bei denen die Implementierer ein wenig kreative Interpretation vornahmen und nicht sklavisch dem Buchstaben des Standards folgten.

Es ist möglichstd::not1 Arbeit in C++ 03 zu machen, indem eine Spezialisierung von std::unary_negate für Prädikate mit Bezug argument_type s Zugabe, aber weder libC++ noch libstdC++ hat dies auch getan.

Aber Sie wissen, wer hat? Boost! Wenn Sie nur Ihren Code ändern, um boost::not1 überall zu verwenden, den Sie gerade verwenden std::not1, everything will work fine. Denken Sie grundsätzlich an den boost Namensraum, als ob es eine C++ 11-kompatible Version von std wäre; Alles, was in C++ 11 funktioniert std Namespace funktioniert wahrscheinlich in C++ 03 boost Namespace.


Caveat, hoffentlich Wegthema: Die Clang-Compiler auf meinem MacBook (Apple LLVM version 4.2 (clang-425.0.28) (based on LLVM 3.2svn)) kollabiert leise Referenzen auch in -std=c++03-Modus, so dass

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

keinen Fehler erzeugt.Stellen Sie sicher, dass Sie keinen Compiler mit diesem falschen Feature verwenden, wenn Sie Ihren C++ 03-Code testen.