Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

std::function const correctness

Suppose I have a callable type like so:

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

Note that mutable_callable has a non-const operator() that modifies a member variable.....

Now suppose I create a std::function out of my type:

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

Now I can do this:

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

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

Now as far as I can tell std::functions operator() is const as per: https://en.cppreference.com/w/cpp/utility/functional/function/operator()

So my gut feeling is that you shouldn't be able to do this.....

But then looking at: https://en.cppreference.com/w/cpp/utility/functional/function/function

This doesn't seem to put any constraints on whether or not the callable type has a constant operator()......

So my question is this: I am correct in assuming that std::function<int()> const& is essentially the same thing as std::function<int()>& that is there is no actually difference between the behavior of the two......and if that is the case why is it not const correct?

like image 758
DarthRubik Avatar asked Dec 04 '19 15:12

DarthRubik


People also ask

What is const correctness in C++?

By Alex Allain. The const keyword allows you to specify whether or not a variable is modifiable. You can use const to prevent modifications to variables and const pointers and const references prevent changing the data pointed to (or referenced).

Can a function be const?

A function becomes const when the const keyword is used in the function's declaration. The idea of const functions is not to allow them to modify the object on which they are called. It is recommended the practice to make as many functions const as possible so that accidental changes to objects are avoided.

Does using const improve performance?

const correctness can't improve performance because const_cast and mutable are in the language, and allow code to conformingly break the rules. This gets even worse in C++11, where your const data may e.g. be a pointer to a std::atomic , meaning the compiler has to respect changes made by other threads.

What will happen if a const object calls a non const member function?

If the function is non-constant, then the function is allowed to change values of the object on which it is being called. So the compiler doesn't allow to create this chance and prevent you to call a non-constant function on a constant object, as constant object means you cannot change anything of it anymore.


1 Answers

This boils down to the same as struct A { int* x; };, where in a const A a; you can modify the value of *(a.x) (but not where it points to). There is a level of indirection in std::function (from the type erasure) through which const is not propagated.

And no, std::function<int()> const& f is not pointless. In a std::function<int()>& f you would be able to assign a different functor to f, which you cannot do in the const case.

like image 100
Max Langhof Avatar answered Nov 04 '22 15:11

Max Langhof