siemanko
siemanko

Reputation: 1409

Forcing non-temporary in RAII by compile Error C++

When one uses lock_guard in C++ like this:

 lock_guard<mutex>(lock);

The compiler complains:

no matching constructor for initialization of 'std::lock_guard<std::mutex>'

Because the correct use is:

 lock_guard<mutex> guard(lock);

I would like to write a custom RAII allocator that also coplains when this happens - I tried disabling copy consturctor and assigment operator, but so far nothing works.

Upvotes: 3

Views: 347

Answers (1)

user2486888
user2486888

Reputation:

I don't know how to achieve your goal, but I guess I know what's happened to lock_guard<mutex>(lock).

Let's do some experiment.

Experiment 1

int(x);
x = 1;
std::cout << x << std::endl;

The experiment reveals we have declared a variable x, even though there is a pair of brackets.

Experiment 2

class Widget
{
};

class WidgetGuard
{
private:
    Widget& widget;
public:
    WidgetGuard(Widget& w)
        : widget(w)
    {}
};

int main()
{
    Widget w1;

    WidgetGuard wg1(w1);
    WidgetGuard(w1);     //Error!
    WidgetGuard{ w1 };   //Pass!
}

We define a Widget class and WidgetGuard class to emulate std::mutex and std::lock_guard. When we try to declare a temporary WidgetGuard with brackets, it gives an error. But doing so with braces compiles.

This can be explained with Experiment 1. The compiler parses WidgetGuard{ w1 } to be "create temporary". But it parses WidgetGuard(w1) to be "declare variable w1"! There are two sources of error: reusing the same name, and no default constructor in WidgetGuard.

Experiment 0

Returning to std::mutex and std::lock_guard, let's try braces...

std::mutex m;
std::lock_guard<std::mutex> {m};

... and it works.

A temporary of std::lock_guard can be created. We just can.

Upvotes: 3

Related Questions