Macro enabling Python style 'with' in C++ I am developing a simple macro that enables Python style 'with' in C++.
I have shamelessly prefixed the macro name with BOOST_ - primarily because there's a similarity to BOOST_FOREACH, and because I didn't want to call it plain WITH.

The motivation are familiar bugs like these:

void bug1() {
    std::unique_lock&lt;std::mutex&gt;(my_mutex);
    // oooops, forgot to give the lock a name
    function_call();
}

void bug2() {
    std::unique_lock&lt;std::mutex&gt; waldo(my_mutex);
    function_call();
    // oooops, forgot to unlock
    other_function_call();
}

void ugly() {
    {
        // intent of explicit scope not as obvious as could be
        std::unique_lock&lt;std::mutex&gt; waldo(my_mutex);
        function_call();
    }
    other_function_call();
}


So here are the questions:


Is this useful to anyone but me?
Is this a bad idea for whatever reason?
Have I overlooked a possibility to implement this in C++03?
Can it be implemented without the is_move_constructible type requirement?
Do you have suggestions for improvement?
(With a twinkle) Should I apply for some speaking time during the C++Now 2015 Lightning Talks and present this?


And here's my implementation:

NOTE: I have considered an alternative signature such as...

BOOST_WITH(type, ...)


...where ... would be the arguments to the constructor. I have decided to stick to this:

#ifndef BOOST_WITH_HPP_INCLUDED
#define BOOST_WITH_HPP_INCLUDED

#include &lt;utility&gt;
#include &lt;type_traits&gt;

// This macro expands to code that can be used in the same way as the standard
// control structures can. Whatever 'exp' returns lives as long as a loop
// variable would in similar context.
//
// Example:
// BOOST_WITH(std::unique_lock&lt;std::mutex&gt;(my_mutex))
//     do_something();
//
// Example:
// BOOST_WITH(Pushed_matrix()) {
//     draw_something();
//     draw_something_else();
// }
#define BOOST_WITH(exp)                                                        \
    if (auto BOOST_WITH_always_true = boost::with_detail::make_true(exp))


namespace boost {
namespace with_detail {

// wraps an object of movable type
// and provides conversion to bool (always true)
template &lt;class T&gt;
struct always_true {
    explicit always_true(T what) : x{std::move(what)} {}
    constexpr operator bool() const { return true; }
    T x;
};

// always_true&lt;T&gt; construction helper
template &lt;class T&gt;
always_true&lt;T&gt; make_true(T&amp;&amp; what) {
    static_assert(std::is_move_constructible&lt;T&gt;::value,
                  "BOOST_WITH requires the scoped object's type to be move "
                  "constructible");
    return always_true&lt;T&gt;{std::forward&lt;T&gt;(what)};
}

}} // namepace boost::with_detail


#endif // BOOST_WITH_HPP_INCLUDED


Finally, a minimal example:

#include "with.hpp"
#include &lt;cassert&gt;
#include &lt;mutex&gt;

// nothing serious, just a prove of concept
struct Lockable {
    Lockable() : locked(false) {}
    void lock() { locked = true; }
    void unlock() { locked = false; }
    bool locked;
};

int main() {
    Lockable the_lock;
    assert(!the_lock.locked);
    BOOST_WITH(std::unique_lock&lt;Lockable&gt;(the_lock))
        assert(the_lock.locked);
    assert(!the_lock.locked);
}
[ Foreword: Note that I'm not going to argue whether or not it is a good idea to invent a new macro-based syntax for this.  I'm only reviewing your code. &mdash; end foreword ]

I think you have been pretty careful and cannot spot any serious issues with your implementation; nice job.

The only thing that I think could be improved is the error reporting.  Your static_assertion fires much too late in the instantiation process such that the error message will end up buried under loads of template error messages.  You can re-structure the instantiation machinery to improve this.

First, provide two overloads of boost::with_detail::make_true:

template &lt;class T&gt;
std::true_type make_true(T&amp;&amp;, std::false_type) {
    static_assert(std::is_move_constructible&lt;T&gt;::value,
                  "BOOST_WITH requires the scoped object's type to be move"
                  " constructible");
    return std::true_type{};  // never executed
}

template &lt;class T&gt;
always_true&lt;T&gt; make_true(T&amp;&amp; what, std::true_type) {
    static_assert(std::is_move_constructible&lt;T&gt;::value, "this is a bug");
    return always_true&lt;T&gt;{std::forward&lt;T&gt;(what)};
}


The static_assertion in the second overload is of course only paranoia and could be omitted.

Second, select the appropriate overload via tag dispatch:

#define BOOST_WITH(RESOURCE)                                        \
  if (auto BOOST_WITH_always_true = boost::with_detail::make_true(  \
      RESOURCE,                                                     \
      std::is_move_constructible&lt;decltype(RESOURCE)&gt;{}))


With this change, if I try to abuse your macro with a wrong type, GCC gives me this pretty straight-forward error message:

In file included from main.cpp:1:0:
boost/with.hpp: In instantiation of ‘std::true_type boost::with_detail::make_true(T&amp;&amp;, std::false_type) [with T = std::mutex; std::true_type = std::integral_constant&lt;bool, true&gt;; std::false_type = std::integral_constant&lt;bool, false&gt;]’:
main.cpp:22:5:   required from here
boost/with.hpp:42:7: error: static assertion failed: BOOST_WITH requires the scoped object's type to be move constructible
       static_assert(std::is_move_constructible&lt;T&gt;::value,


Compare this with what we would have got before.

Note that we cannot simply put static_assert(false, …); inside the make_true body because it would fire unconditionally on every compilation.  It is necessary to make the asserted condition dependent on the template argument.  Of course, any other template instantiated with T that always yields false would do equally well but using std::is_move_constructible (again) seems easiest.