2012-10-05 14 views
8

Ho bisogno di creare un predicato dalla funzione membro associato, quindi l'ho spostato in un boost::function<bool(SomeObject const &)>. Sembra che stia bene e tutto, ma ho anche avuto bisogno di negarlo in un caso. TuttaviaRiferimento collasso sotto C++ 03

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

non compila sotto MSVC++ 9.0 (Visual Studio 2008), lamentando che il riferimento per fare riferimento non è valido:

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 

Il problema è che boost::function definisce il argument_type come SomeObject const & e la std::unary_negate<_Fn1> istanziato da std::not1 tenta internamente di utilizzare const typename _Fn1::argument_type& e il compilatore lo rifiuta perché T::argument_type è già un riferimento. Sono certo che questo dovrebbe essere compilato in C++ 11, ma questo è un vecchio compilatore che è solo C++ 03. Così mi piacerebbe sapere chi è la colpa è:

  • del compilatore, perché dovrebbe crollare il riferimento (apparently not),
  • della libreria standard, perché dovrebbe essere preparato a gestire funtori che prendono i riferimenti (a quanto pare non, perché la specifica definisce unary_negate con const typename Predicate::argument_type& x argomento),
  • Boost, perché argument_type non dovrebbe essere di riferimento anche quando l'argomento reale è o
  • mia, perché boost::function non deve essere utilizzato con argomenti di riferimento?
+0

Compila sotto altri compilatori? – eh9

+0

@ eh9: Con gcc compila, almeno per gli obiettivi mingw32 e cygwin. –

+0

@ eh9: Ma non è troppo rilevante per la domanda; chi è la colpa è e perché dipende dalle specifiche. –

risposta

1

L'errore non è certo quello di Boost; boost::function è fondamentalmente solo std::function, con la stessa semantica. E anche gli boost::function s con i parametri di riferimento funzionano bene. Non puoi semplicemente usarli con std::not1 o il resto del materiale <functional>.

C++ 11's reference-crollo rende std::not1 il modo in cui si penserebbe che dovrebbe. Il modo in cui std::not1 è stato specificato in C++ 03 non potrebbe funzionare senza riferimento-compressione - tranne nelle implementazioni in cui gli implementatori hanno fatto un po 'di interpretazione creativa piuttosto che seguire pedissequamente la lettera dello standard.

E 'possibile fare std::not1 lavoro in C++ 03 con l'aggiunta di una specializzazione di std::unary_negate per predicati con riferimento argument_type s, ma né libC++ né libstdC++ ha fatto.

Ma sai chi ha? Aumenta! Se si modifica il proprio codice per utilizzare boost::not1 ovunque al momento si utilizza std::not1, everything will work fine. Fondamentalmente, si pensi allo spazio dei nomi boost come se fosse una versione compatibile con C++ 11 di std; tutto ciò che funziona nello spazio dei nomi std di C++ 11 probabilmente funziona nello spazio dei nomi boost di C++ 03.


Caveat, si spera off-topic: Il compilatore Clang sul mio MacBook (Apple LLVM version 4.2 (clang-425.0.28) (based on LLVM 3.2svn)) crolla in silenzio riferimenti anche in modalità -std=c++03, in modo che

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

produce alcun errore.Quando testate il vostro codice C++ 03, assicuratevi di non usare un compilatore con questa disfunzione.

Problemi correlati