poprawność std :: function const


11

Załóżmy, że mam typ na żądanie:

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

Zauważ, że mutable_callablema non-const, operator()która modyfikuje zmienną składową .....

Załóżmy teraz, że utworzyłem std::functionz mojego typu:

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

Teraz mogę to zrobić:

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

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

Teraz, o ile mogę powiedzieć, std::functions operator()jest constwedług: https://en.cppreference.com/w/cpp/utility/functional/function/operator ()

Więc mam przeczucie, że nie powinieneś być w stanie tego zrobić .....

Ale potem patrząc na: https://en.cppreference.com/w/cpp/utility/functional/function/function

To nie wydaje się ograniczać, czy typ wywoływalny ma stałą operator()......

Moje pytanie brzmi więc: mam rację, zakładając, że std::function<int()> const&jest to w zasadzie to samo, std::function<int()>&że nie ma żadnej różnicy między zachowaniem tych dwóch ...... a jeśli tak, to dlaczego nie jest constpoprawne?


@ MaxLanghof No ..... std::functionma odpowiednik struct a{ std::any x; };w nim .....
DarthRubik

Oto mały fragment wewnętrznych elementów std::functionimplementacji MSVC : i.stack.imgur.com/eNenN.png gdzie using _Ptrt = _Func_base<_Ret, _Types...>. Opieram swoją sprawę.
Max Langhof,

Odpowiedzi:


3

To sprowadza się do tego samego, jak struct A { int* x; };, gdzie w sposób const A a;można zmodyfikować wartość z *(a.x)(ale nie tam, gdzie to wskazuje). Istnieje poziom pośrednictwa w std::function(od typu wymazywania), przez który constnie jest propagowany.

I nie, std::function<int()> const& fnie jest bez sensu. W przypadku std::function<int()>& fmożesz przypisać inny funktor f, czego nie można zrobić w tym constprzypadku.


Tak ... to naprawdę ma sens ... na pierwszy rzut oka jednak
mylące

Uważam, że to wada projektowa. Ta pośrednia powinna być szczegółem implementacji przejrzystym dla użytkownika, a ciągłość może być propagowana przy użyciu niektórych metaprogramowania.
Igor R.

@IgorR. Tak, stałość może być propagowana. std::vectorrobi to, std::unique_ptrnie robi. Wydaje mi się, że std::functiontak naprawdę nie chodzi o wyrażanie niezmienników stanu funktora. Może moglibyśmy zmienić przeznaczenie obrzydliwych typów funkcji (tj. std::function<int() const>) W celu rozróżnienia?
Max Langhof,

unique_ptrnie powinien propagować stałości, tak jak zwykły wskaźnik. I std::function<int() const>nie chciałbym się skompilować.
Igor R.

@IgorR. Wiem. Chodzi mi o to, że niektóre części standardowej biblioteki to robią, a inne nie. Która kategoria std::functionpowinna należeć do mnie nie jest jasne. I std::function<int() const>był hipotetyczny - oczywiście, że teraz się nie kompiluje, ale czy spełniłby on np. OP tutaj, gdyby można go było uznać za ważny, wyrażając „można przypisać funktory tylko z operator() const(lub bezpaństwowcami)”? (nawet jeśli za kulisami byłoby to dość okropne, ze względu na stosowanie ohydnych typów funkcji)?
Max Langhof,
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.