How to avoid C++ anonymous objects

I have seen an interesting trick in one codebase, but it only works if your scoped_lock type is not a template (std::scoped_lock is).

#define scoped_lock(x) static_assert(false, "you forgot the variable name")

If you use the class correctly, you have

scoped_lock lock(mutex);

and since the scoped_lock identifier isn't followed by an open paren, the macro won't trigger and the code will remain as it is. If you write\

scoped_lock(mutex);

the macro will trigger and the code will be substituted with

static_assert(false, "you forgot the variable name");

This will generate an informative message.

If you use a qualified name

threads::scoped_lock(mutext);

then the result will still not compile, but the message won't be as nice.

Of course, if your lock is a template, the bad code is

scoped_lock<mutex_type>(mutex);

which won't trigger the macro.


You can use a class and deleted function with the same name. Unfortunately this requires adding "class" keyword before the type.

class Guard
{
public:
  explicit Guard(void)
  {
  }
};

static void Guard(void) = delete;

int main()
{
  // Guard(); // Won't compile
  // Guard g; // Won't compile
  class Guard g;
}

No, unfortunately there is no way to do this, as I explored in a blog post last year.

In it, I concluded:

I guess the moral of the story is to remember this story when using scoped_locks.


You can try to force all programmers in your team to use a macro, or a range-for trick, but then if you could guarantee that in every case then you'd be able to guarantee catching this bug in every case also.

You are looking for a way to programmatically catch this specific mistake when it's made, and there is none.

Tags:

C++

G++