La seguente espressione utilizzando is_assignable
rendimenti true
quando si utilizza gcc 4.7 e aumentare 1.49:risultati imprevisti quando si utilizza std :: is_assignable, boost :: funzione e nullptr
typedef boost::function<void()> F;
std::is_assignable<F, std::nullptr_t>::value
Tuttavia, questo codice non riesce a compilare:
boost::function<void()> f;
f = nullptr;
produttrici di questi messaggi di errore:
In file included from c:\mingw\bin\../lib/gcc/i686-pc-mingw32/4.7.0/../../../../include/boost/function/detail/maybe_include.hpp:13:0,
from c:\mingw\bin\../lib/gcc/i686-pc-mingw32/4.7.0/../../../../include/boost/function/detail/function_iterate.hpp:14,
from c:\mingw\bin\../lib/gcc/i686-pc-mingw32/4.7.0/../../../../include/boost/preprocessor/iteration/detail/iter/forward1.hpp:47,
from c:\mingw\bin\../lib/gcc/i686-pc-mingw32/4.7.0/../../../../include/boost/function.hpp:64,
from ..\main.cpp:8:
c:\mingw\bin\../lib/gcc/i686-pc-mingw32/4.7.0/../../../../include/boost/function/function_template.hpp: In instantiation of 'static void boost::detail::function::void_function_obj_invoker0<FunctionObj, R>::invoke(boost::detail::function::function_buffer&) [with FunctionObj = std::nullptr_t; R = void]':
c:\mingw\bin\../lib/gcc/i686-pc-mingw32/4.7.0/../../../../include/boost/function/function_template.hpp:907:60: required from 'void boost::function0<R>::assign_to(Functor) [with Functor = std::nullptr_t; R = void]'
c:\mingw\bin\../lib/gcc/i686-pc-mingw32/4.7.0/../../../../include/boost/function/function_template.hpp:722:7: required from 'boost::function0<R>::function0(Functor, typename boost::enable_if_c<boost::type_traits::ice_not<boost::is_integral<Functor>::value>::value, int>::type) [with Functor = std::nullptr_t; R = void; typename boost::enable_if_c<boost::type_traits::ice_not<boost::is_integral<Functor>::value>::value, int>::type = int]'
c:\mingw\bin\../lib/gcc/i686-pc-mingw32/4.7.0/../../../../include/boost/function/function_template.hpp:1042:16: required from 'boost::function<R()>::function(Functor, typename boost::enable_if_c<boost::type_traits::ice_not<boost::is_integral<Functor>::value>::value, int>::type) [with Functor = std::nullptr_t; R = void; typename boost::enable_if_c<boost::type_traits::ice_not<boost::is_integral<Functor>::value>::value, int>::type = int]'
c:\mingw\bin\../lib/gcc/i686-pc-mingw32/4.7.0/../../../../include/boost/function/function_template.hpp:1083:5: required from 'typename boost::enable_if_c<boost::type_traits::ice_not<boost::is_integral<Functor>::value>::value, boost::function<R()>&>::type boost::function<R()>::operator=(Functor) [with Functor = std::nullptr_t; R = void; typename boost::enable_if_c<boost::type_traits::ice_not<boost::is_integral<Functor>::value>::value, boost::function<R()>&>::type = boost::function<void()>&]'
..\main.cpp:172:6: required from here
c:\mingw\bin\../lib/gcc/i686-pc-mingw32/4.7.0/../../../../include/boost/function/function_template.hpp:153:11: error: '* f' cannot be used as a function
Inoltre, questa espressione restituisce false
:
typedef boost::function<void()> G;
std::is_assignable<G, decltype(NULL)>::value
ma questo codice si compila:
boost::function<void()> g;
g = NULL;
I risultati di is_assignable
non sembrano riflettere correttamente la funzionalità di boost::function
. Sto facendo qualcosa di sbagliato qui? (Sto avendo problemi a dare un senso ai messaggi di errore.)
Ho pensato che i tratti del tipo dovevano essere un modo affidabile per determinare la funzionalità delle classi utilizzate nei modelli. I caratteri tipografici forniti in C++ 11 sono semplicemente incompatibili con la funzione boost ::?
di dare a questo un po 'di contesto, ho lavorato su diversi progetti personali per familiarizzare meglio me stesso con le nuove caratteristiche di C++ 11. Per questo particolare progetto, sto tentando di creare una classe che memorizza una funzione chiamabile che può essere "disattivata". Questo è più o meno quello che sto cercando di fare:
template <typename F>
class callable_function
{
public:
callable_function(F func) : func_(func)
{
/* func_ is initially active */
}
void call()
{
if (/* func_ is active */) func_();
}
void deactivate()
{
/* set func_ to deactive */
}
private:
F func_;
};
per i blocchi /* func_ is active */
e /* set func_ to deactive */
, voglio fornire due implementazioni diverse che vengono selezionati in fase di compilazione a seconda delle proprietà di F
. Se nullptr
possono essere assegnati ad func_
e func_
può essere utilizzato in un contesto booleano, allora voglio utilizzare il seguente (che è ciò che viene selezionato per i puntatori funzione built-in e std::function
):
template <typename F>
class callable_function
{
public:
callable_function(F func) : func_(func) {}
void call()
{
if (func_) func_();
}
void deactivate()
{
func_ = nullptr;
}
private:
F func_;
};
If nullptr
non può essere assegnato a func_
, quindi voglio memorizzare un valore booleano aggiuntivo all'interno della classe che memorizza lo stato "attivo". Questa implementazione è selezionato per funtori e funzioni lambda:
template <typename F>
class callable_function
{
public:
callable_function(F func) : func_(func), active_(true) {}
void call()
{
if (active_) func_();
}
void deactivate()
{
active_ = false;
}
private:
F func_;
bool active_;
};
Dal nullptr
attualmente non possono essere assegnati a boost::function
, mi sarei aspettato la seconda esecuzione a scelta. Tuttavia, poiché true
restituisce true
per e nullptr
, viene invece selezionata la prima implementazione, che genera un errore di compilazione nella funzione deactivate
.
Nota a margine: qualsiasi motivo per non utilizzare 'std :: function' invece di' boost :: function'? –
Mi piacerebbe essere in grado di gestire i casi più comuni, che credo avrebbero incluso i puntatori di funzioni, i funtori, le funzioni lambda, 'std :: function' e' boost :: function'. La mia versione attuale funziona per tutto eccetto per 'boost :: function', a causa del problema discusso sopra. Dato che questo è solo un progetto di apprendimento, non ha molta importanza, ma se ci sono dei caveat o "trucchi" sui tratti del C++ 11, mi piacerebbe capire cosa sono. –
Non penso sia un problema con i tratti di tipo C++, piuttosto un problema con 'boost :: function'. 'std :: function' ha un' operator = 'che accetta un' std :: nullptr_t' tuttavia 'boost :: function' non ha questa capacità (se si nota l'operatore di assegnazione nel messaggio di errore la sua funzione' boost ::: : operator = (Functor) '). Quindi, i tratti di tipo C++ 11 sono corretti nel restituire 'true' perché ** è ** assegnabile, tuttavia' boost :: function' manca della funzionalità per gestire 'nullptr'. Inoltre, 'std :: is_assignable :: value' è corretto nel restituire false poiché' decltype (NULL) 'è di tipo' int'. –