std :: function const correttezza


11

Supponiamo che io abbia un tipo richiamabile in questo modo:

struct mutable_callable
{
    int my_mutable = 0;
    int operator()() { // Not const
        return my_mutable++;
    }
};

Nota che mutable_callableha una non const operator()che modifica una variabile membro .....

Supponiamo ora di creare un std::functionfuori dal mio tipo:

std::function<int()> foo = mutable_callable{};

Ora posso fare questo:

void invoke(std::function<int()> const& z)
{
    z();
}

int main()
{
    invoke(foo); // foo changed.....oops
}

Ora, per quanto ne so std::function, operator()è constcome per: https://en.cppreference.com/w/cpp/utility/functional/function/operator ()

Quindi la mia sensazione è che non dovresti essere in grado di farlo .....

Ma poi guardando: https://en.cppreference.com/w/cpp/utility/functional/function/function

Questo non sembra porre alcun vincolo sul fatto che il tipo richiamabile abbia o meno una costante operator()......

Quindi la mia domanda è questa: ho ragione nel presumere che std::function<int()> const&sia essenzialmente la stessa cosa, perché in std::function<int()>&realtà non c'è differenza tra il comportamento dei due ... e se è così, perché non è constcorretto?


@MaxLanghof No ..... std::functionha l'equivalente di un struct a{ std::any x; };in esso .....
DarthRubik

Ecco un piccolo frammento degli interni dell'implementazione di MSVC std::function: i.stack.imgur.com/eNenN.png dove using _Ptrt = _Func_base<_Ret, _Types...>. Non ho niente da aggiungere.
Max Langhof,

Risposte:


3

Questo si riduce allo stesso struct A { int* x; };, dove in a const A a;puoi modificare il valore di *(a.x)(ma non dove punta). Esiste un livello di riferimento indiretto std::function(dal tipo di cancellazione) attraverso il quale constnon viene propagato.

E no, std::function<int()> const& fnon è inutile. In a std::function<int()>& fsaresti in grado di assegnare un diverso funzione f, cosa che non puoi fare nel constcaso.


Sì ..... questo in realtà ha molto senso ..... ancora confuso a prima vista però
DarthRubik

Credo che sia un difetto di design. Questa indiretta dovrebbe essere un dettaglio di implementazione trasparente per l'utente, e la costanza potrebbe essere propagata usando qualche metaprogrammazione.
Igor R.

@IgorR. Sì, la costanza potrebbe essere propagata. std::vectorfa questo, std::unique_ptrno. Sento che std::functionnon si tratta in realtà di esprimere invarianti dello stato di funzione. Forse potremmo riutilizzare tipi di funzione abominevoli (cioè std::function<int() const>) per distinguere?
Max Langhof,

unique_ptrnon dovrebbe propagare la costanza, come non accade il puntatore normale. E std::function<int() const>non compilare.
Igor R.

@IgorR. Lo so. Il mio punto era che alcune parti della libreria standard lo fanno e altre no. In quale categoria std::functionrientrare non mi è chiaro. E l' std::function<int() const>ipotetico era - ovviamente non si compila ora, ma soddisferebbe ad esempio l'OP qui se ciò potesse essere reso valido, esprimendo "si possono assegnare solo i funzioni con un operator() const(o apolidi)"? (anche se dietro le quinte sarebbe abbastanza atroce, a causa dell'uso di abominevoli tipi di funzione)?
Max Langhof,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.