std :: function const correctness

11

Misalkan saya memiliki tipe callable seperti:

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

Catatan yang mutable_callablememiliki non-const operator()yang memodifikasi variabel anggota .....

Sekarang anggaplah saya membuat std::functionkeluar dari tipeku:

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

Sekarang saya bisa melakukan ini:

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

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

Sekarang sejauh yang saya tahu std::functions operator()adalah constsebagai per: https://en.cppreference.com/w/cpp/utility/functional/function/operator ()

Jadi firasatku adalah kamu tidak seharusnya bisa melakukan ini .....

Tetapi kemudian melihat: https://en.cppreference.com/w/cpp/utility/functional/function/function

Ini sepertinya tidak menempatkan kendala pada apakah tipe callable memiliki konstanta operator()......

Jadi pertanyaan saya adalah ini: Saya benar dalam mengasumsikan bahwa std::function<int()> const&pada dasarnya hal yang sama dengan std::function<int()>&yang ada sebenarnya tidak ada perbedaan antara perilaku keduanya ...... dan jika itu masalahnya mengapa tidak constbenar?

DarthRubik
sumber
@ MaxLanghof No ..... std::functionmemiliki yang setara dengan struct a{ std::any x; };di dalamnya .....
DarthRubik
Berikut ini adalah potongan kecil dari internal std::functionimplementasi MSVC : i.stack.imgur.com/eNenN.png di mana using _Ptrt = _Func_base<_Ret, _Types...>. Saya mengistirahatkan koper saya.
Max Langhof

Jawaban:

3

Ini bermuara sama seperti struct A { int* x; };, di mana dalam const A a;Anda dapat memodifikasi nilai dari *(a.x)(tapi tidak di mana itu menunjuk ke). Ada tingkat tipuan dalam std::function(dari tipe penghapusan) melalui mana consttidak diperbanyak.

Dan tidak, std::function<int()> const& ftidak ada gunanya. Dalam std::function<int()>& fAnda akan dapat menetapkan functor yang berbeda f, yang tidak dapat Anda lakukan dalam constkasus ini.

Max Langhof
sumber
Yup ..... itu benar-benar masuk akal ..... masih membingungkan pada pandangan pertama
DarthRubik
Saya percaya itu cacat desain. Tipuan ini harus menjadi detail implementasi transparan kepada pengguna, dan ketegasan dapat diperbanyak menggunakan beberapa metaprogramming.
Igor R.
@IgorR. Ya, keteguhan bisa diperbanyak. std::vectorapakah ini, std::unique_ptrtidak. Saya merasa std::functiontidak benar-benar tentang mengekspresikan invarian dari negara functor. Mungkin kita bisa mengubah jenis fungsi yang menjijikkan (yaitu std::function<int() const>) untuk membedakan?
Max Langhof
unique_ptrseharusnya tidak menyebarkan kesegaran, karena pointer biasa tidak. Dan std::function<int() const>tidak akan dikompilasi.
Igor R.
@IgorR. Aku tahu. Maksud saya adalah bahwa beberapa bagian dari perpustakaan standar melakukannya dan beberapa lainnya tidak. Menurut saya kategori mana yang std::functiontidak jelas. Dan std::function<int() const>itu adalah hipotetis - tentu saja itu tidak dikompilasi sekarang, tetapi apakah itu memuaskan misalnya OP di sini jika itu dapat dibuat valid, dengan menyatakan "hanya dapat ditugaskan fungsi dengan operator() const(atau yang tanpa kewarganegaraan)"? (bahkan jika di belakang layar itu akan sangat mengerikan, karena menggunakan jenis fungsi yang menjijikkan)?
Max Langhof