La siguiente expresión usando is_assignable
vuelve true
cuando se utiliza gcc 4.7 y 1.49 impulsar:resultados inesperados cuando se usa std :: is_assignable, impulsar :: función y nullptr
typedef boost::function<void()> F;
std::is_assignable<F, std::nullptr_t>::value
Sin embargo, este código falla al compilar:
boost::function<void()> f;
f = nullptr;
productoras de estos mensajes de error:
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
Además, esta expresión devuelve false
:
typedef boost::function<void()> G;
std::is_assignable<G, decltype(NULL)>::value
pero este código se compila: no parecen
boost::function<void()> g;
g = NULL;
Los resultados de is_assignable
para reflejar adecuadamente la funcionalidad de boost::function
. ¿Estoy haciendo algo mal aquí? (Tengo problemas para dar sentido a los mensajes de error.)
Pensé que los rasgos de tipo se suponía que eran una forma confiable de determinar la funcionalidad de las clases utilizadas en las plantillas. ¿Los rasgos de tipo proporcionados en C++ 11 son simplemente incompatibles con boost :: function?
para dar a este un poco de contexto, he estado trabajando en varios proyectos personales para familiarizarse mejor a mí mismo con las nuevas características de C++ 11. Para este proyecto en particular, intento crear una clase que almacene una función invocable que pueda ser "desactivada". Esto es más o menos lo que yo estoy tratando de hacer:
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_;
};
Para los /* func_ is active */
y /* set func_ to deactive */
bloques, quiero ofrecer dos implementaciones diferentes que se seleccionan en tiempo de compilación en función de las propiedades de F
. Si nullptr
se pueden asignar a func_
y func_
se puede utilizar en un contexto booleano, entonces yo quiero usar lo siguiente (que es lo que se ha seleccionado para los punteros de las funciones integradas y 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
no puede Asignar a func_
, luego quiero almacenar un valor booleano adicional dentro de la clase que almacena el estado "activo". Esta aplicación es seleccionado para funtores y funciones 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_;
};
Desde nullptr
actualmente no se pueden asignar a boost::function
, yo esperaría que la segunda aplicación que se ha elegido. Sin embargo, dado que is_assignable
está devolviendo true
para boost::function
y nullptr
, se selecciona la primera implementación en su lugar, lo que da como resultado un error de compilación en la función deactivate
.
Nota al margen: ¿Alguna razón para no usar 'std :: function' en lugar de' boost :: function'? –
Me gustaría poder manejar los casos más comunes, que creí que incluirían punteros de funciones incorporados, funtores, funciones lambda, 'std :: function', y' boost :: function'. Mi versión actual funciona para todo, excepto para 'boost :: function', debido al problema mencionado anteriormente. Dado que este es solo un proyecto de aprendizaje, realmente no importa, pero si hay advertencias o "errores" en los rasgos de tipo C++ 11, me gustaría entender cuáles son. –
No creo que sea un problema con los rasgos de tipo C++, sino un problema con 'boost :: function'. 'std :: function' tiene un' operator = 'que toma' std :: nullptr_t' pero 'boost :: function' carece de esta capacidad (si observa el operador de asignación en su mensaje de error es' boost :: function: : operator = (Functor) '). Entonces, los rasgos de tipo C++ 11 son correctos al devolver 'true' porque ** es ** asignable, sin embargo' boost :: function' carece de la funcionalidad para manejar 'nullptr'. Además, 'std :: is_assignable :: value' es correcto al devolver falso porque' decltype (NULL) 'es del tipo' int'. –