std :: function const correção

11

Suponha que eu tenha um tipo de chamada assim:

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

Observe que mutable_callablepossui um não-const operator()que modifica uma variável de membro .....

Agora, suponha que eu crie um std::functionfora do meu tipo:

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

Agora eu posso fazer isso:

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

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

Agora, tanto quanto eu posso dizer, std::functions operator()é o seguinte const: https://en.cppreference.com/w/cpp/utility/functional/function/operator ()

Então, meu pressentimento é que você não deve ser capaz de fazer isso ...

Mas, em seguida, consulte: https://en.cppreference.com/w/cpp/utility/functional/function/function

Isso não parece restringir se o tipo de chamada tem ou não uma constante operator()......

Portanto, minha pergunta é a seguinte: estou certo ao supor que std::function<int()> const&é essencialmente a mesma coisa std::function<int()>&que não existe realmente diferença entre o comportamento dos dois ...... e, se for esse o caso, por que não está constcorreto?

DarthRubik
fonte
@MaxLanghof No ..... std::functiontem o equivalente a um struct a{ std::any x; };.....
DarthRubik
Aqui está um pequeno trecho das informações internas da std::functionimplementação do MSVC : i.stack.imgur.com/eNenN.png onde using _Ptrt = _Func_base<_Ret, _Types...>. Eu descanso meu caso.
precisa

Respostas:

3

Isso se resume ao mesmo que struct A { int* x; };, em que const A a;você pode modificar o valor de *(a.x)(mas não para onde aponta). Existe um nível de indireção std::function(a partir do tipo apagamento) pelo qual constnão é propagado.

E não, std::function<int()> const& fnão é inútil. Em um std::function<int()>& fvocê seria capaz de atribuir um functor diferente f, o que você não pode fazer no constcaso.

Max Langhof
fonte
Yup ..... que realmente faz muito sentido ..... ainda confuso à primeira vista embora
DarthRubik
Eu acredito que é uma falha de design. Esse indireto deve ser um detalhe de implementação transparente para o usuário e a constância pode ser propagada usando alguma metaprogramação.
Igor R.
@IgorR. Sim, a constância pode ser propagada. std::vectorfaz isso, std::unique_ptrnão faz. eu sintostd::function não é realmente sobre expressar invariantes do estado functor. Talvez pudéssemos redirecionar tipos de funções abomináveis ​​(ie std::function<int() const>) para distinguir?
precisa
unique_ptrnão deve propagar constness, como o ponteiro regular não. E std::function<int() const>não compilaria.
Igor R.
@IgorR. Eu sei. Meu argumento era que algumas partes da biblioteca padrão fazem isso e outras não. Qual categoria std::functiondeve se encaixar não está clara para mim. E isso std::function<int() const>era hipotético - é claro que não compila agora, mas seria satisfatório, por exemplo, o OP aqui se isso pudesse ser validado, expressando "só podem ser atribuídos atribuidores de função com operator() const(ou sem estado)"? (mesmo nos bastidores, isso seria bastante atroz, devido ao uso de tipos de funções abomináveis)?
precisa