Is it possible to explicitly create temporary variables in C ++?

Some people warn that locks can be misused by writing:

std::unique_lock<std::mutex>(mutex); 

instead of the following correct statement:

 std::unique_lock<std::mutex> lock(mutex); 

those. create an unnamed temporary variable instead of a local variable. The temporary variable will be immediately destroyed and prematurely unlock the mutexes.

See for example the gperftools header (line 321-324) :

 // Catch bug where variable name is omitted, eg MutexLock (&mu); #define MutexLock(x) COMPILE_ASSERT(0, mutex_lock_decl_missing_var_name) #define ReaderMutexLock(x) COMPILE_ASSERT(0, rmutex_lock_decl_missing_var_name) #define WriterMutexLock(x) COMPILE_ASSERT(0, wmutex_lock_decl_missing_var_name) 

This macro is written to protect such use cases again.

But can this happen? Apparently, a fairly recent GCC or clang will lead to errors in this case:

 #include <iostream> class Mutex {}; class Lock { public: explicit Lock(Mutex */* dummy */) { std::cout << __PRETTY_FUNCTION__ << std::endl; } ~Lock() { std::cout << __PRETTY_FUNCTION__ << std::endl; } }; int main() { Mutex mutex; { Lock l(&mutex); } { Lock(&mutex); // This line does not compile. } return 0; } 

And the error:

 g++ foo.cpp foo.cpp:17:11: error: declaration of reference variable 'mutex' requires an initializer Lock(&mutex); ^~~~~ 1 error generated. 

Can anyone demonstrate a reproductive case where such a macro catches a real mistake? While I can’t come up with.

+6
source share
1 answer

In fact, you are saved using an ambiguity rule for things that can be declared (they are parsed as declarations, not expressions) in combination with a rule that requires link initialization.

It will not save you here:

 std::mutex m; int main(){ std::unique_lock<std::mutex>(m); // m is a local default-constructed unique_lock } 

or here:

 struct C { Mutex m; } c; int main() { Lock(&c.m); // Constructs and destroys a temporary lock. } 
+4
source

All Articles