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_callabletiene una no constante operator()que modifica una variable miembro .....
Ahora suponga que creo un std::functionfuera 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::functions operator()es constsegú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 constcorrecto?
fuente

std::functiontiene el equivalente a astruct a{ std::any x; };en él .....std::functionimplementació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 cualconstno se propaga.Y no,
std::function<int()> const& fno tiene sentido. En unstd::function<int()>& f, podría asignar un functor diferentef, lo que no puede hacer en elconstcaso.fuente
std::vectorhace esto,std::unique_ptrno lo hace. Sinstd::functionembargo, 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_ptrno debe propagar la constidad, como no lo hace el puntero regular. Ystd::function<int() const>no compilaría.std::functiondeberí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)?