Supongamos que tengo un tipo invocable como este:
struct mutable_callable
{
int my_mutable = 0;
int operator()() { // Not const
return my_mutable++;
}
};
Tenga en cuenta que mutable_callable
tiene una no constante operator()
que modifica una variable miembro .....
Ahora suponga que creo un std::function
fuera de mi tipo:
std::function<int()> foo = mutable_callable{};
Ahora puedo hacer esto:
void invoke(std::function<int()> const& z)
{
z();
}
int main()
{
invoke(foo); // foo changed.....oops
}
Ahora, por lo que puedo decir, std::function
s operator()
es const
según:
https://en.cppreference.com/w/cpp/utility/functional/function/operator ()
Así que mi intuición es que no deberías poder hacer esto .....
Pero luego mirando: https://en.cppreference.com/w/cpp/utility/functional/function/function
Esto no parece poner ninguna restricción sobre si el tipo invocable tiene o no una constante operator()
......
Entonces mi pregunta es la siguiente: estoy en lo cierto al suponer que std::function<int()> const&
es esencialmente lo mismo, ya std::function<int()>&
que no existe una diferencia real entre el comportamiento de los dos ... y si ese es el caso, ¿por qué no es const
correcto?
fuente
std::function
tiene el equivalente a astruct a{ std::any x; };
en él .....std::function
implementación de MSVC : i.stack.imgur.com/eNenN.png dondeusing _Ptrt = _Func_base<_Ret, _Types...>
. Yo descanso mi caso.Respuestas:
Esto se reduce a lo mismo que
struct A { int* x; };
, dondeconst A a;
puede modificar el valor de*(a.x)
(pero no a dónde apunta). Hay un nivel de indirección enstd::function
(desde el tipo de borrado) a través del cualconst
no se propaga.Y no,
std::function<int()> const& f
no tiene sentido. En unstd::function<int()>& f
, podría asignar un functor diferentef
, lo que no puede hacer en elconst
caso.fuente
std::vector
hace esto,std::unique_ptr
no lo hace. Sinstd::function
embargo, creo que no se trata realmente de expresar invariantes del estado functor. ¿Quizás podríamos reutilizar tipos de funciones abominables (es decirstd::function<int() const>
) para distinguir?unique_ptr
no debe propagar la constidad, como no lo hace el puntero regular. Ystd::function<int() const>
no compilaría.std::function
debería caer no me queda claro. Y estostd::function<int() const>
era hipotético, por supuesto, no se compila ahora, pero ¿satisfaría, por ejemplo, el OP aquí si eso pudiera hacerse válido, expresando "solo se pueden asignar functores con unoperator() const
(o apátridas)"? (incluso si detrás de escena sería bastante atroz, debido al uso de tipos de funciones abominables)?