std :: функція const правильність


11

Припустимо, я маю такий тип дзвінка:

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

Зауважте, що mutable_callable має non-const, operator()що змінює змінну члена .....

Тепер припустимо, що я створюю std::functionсвій тип:

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

Тепер я можу це зробити:

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

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

Тепер, наскільки я можу сказати std::function, operator()єconst відповідає: https://en.cppreference.com/w/cpp/utility/functional/function/operator ()

Тож моє відчуття кишки полягає в тому, що ти не повинен цього робити ...

Але потім дивлячись: https://en.cppreference.com/w/cpp/utility/functional/function/function

Це, здається, не ставить обмежень щодо того, чи має тип виклику постійний чи ні operator()......

Отже, моє запитання таке: я правильно вважаю, що std::function<int()> const&це по суті те саме, що і std::function<int()>&те, що фактично немає різниці між поведінкою обох ......, і якщо це так, чому це не constправильно?


@MaxLanghof Ні ..... std::functionмає еквівалент а struct a{ std::any x; };в ньому .....
DarthRubik

Ось невеликий фрагмент внутрішніх даних реалізації MSVC std::function: i.stack.imgur.com/eNenN.png where using _Ptrt = _Func_base<_Ret, _Types...>. Я решту своєї справи.
Макс Ленгоф

Відповіді:


3

Це зводиться до того ж , як struct A { int* x; };, де в const A a;ви можете змінити значення з *(a.x)(але не там , де він вказує). Існує рівень опосередкованості в std::function(від типу стирання), через який constне поширюється.

І ні, std::function<int()> const& fне безглуздо. У a std::function<int()>& fви зможете призначити інший функтор f, чого ви не можете зробити у constвипадку.


Так ... насправді це має багато сенсу ..... все ще бентежить на перший погляд, хоча
DarthRubik

Я вважаю, що це вада дизайну. Ця опосередкованість повинна бути детальною інформацією про реалізацію, прозорою для користувача, і чіткість може бути поширена за допомогою деякої метапрограмування.
Ігор Р.

@IgorR. Так, незмінність може бути поширена. std::vectorробить це, std::unique_ptrне робить. Я вважаю std::function, що насправді не про вираження інваріантів стану функтора. Може, ми могли б змінити гидотні типи функцій (тобто std::function<int() const>), щоб розрізнити?
Макс Ленгоф

unique_ptrне повинно поширювати constness, як це не робить звичайний покажчик. І std::function<int() const>не збирався б.
Ігор Р.

@IgorR. Я знаю. Моя думка полягала в тому, що деякі частини стандартної бібліотеки роблять це, а інші - ні. До якої категорії std::functionслід потрапити, мені незрозуміло. І це std::function<int() const>було гіпотетичним - це, звичайно, не складається зараз, але чи задовольнило б це, наприклад, ОП тут, якщо це можна зробити дійсним, висловлюючи "можна призначити лише функціонерів з operator() const(або без громадянства)"? (навіть якщо за лаштунками це було б досить жорстоко, через використання гидотних типів функцій)?
Макс Лангхоф
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.