Для многих классов RAII "охранников" создание экземпляров анонимных переменных вообще не имеет смысла:
{
std::lock_guard<std::mutex>{some_mutex};
// Does not protect the scope!
// The unnamed instance is immediately destroyed.
}
{
scope_guard{[]{ cleanup(); }};
// `cleanup()` is executed immediately!
// The unnamed instance is immediately destroyed.
}
From this article:
Анонимные переменные в C ++ имеют «область выражения», что означает, что они уничтожаются в конце выражения, в котором они созданы.
Есть ли способ запретить пользователю создавать их экземпляры без имени? ("Предотвратить" может быть слишком сильным - "сделать это очень сложно" также допустимо).
Я могу придумать два возможных обходных пути, но они приводят к синтаксическим накладным расходам при использовании класса:
Скройте класс в пространстве имен
detail
и укажите макрос.namespace detail { class my_guard { /* ... */ }; }; #define SOME_LIB_MY_GUARD(...) \ detail::my_guard MY_GUARD_UNIQUE_NAME(__LINE__) {__VA_ARGS__}
Это работает, но является хакерским.
Разрешить пользователю использовать охрану только через функцию более высокого порядка.
template <typename TArgTuple, typename TF> decltype(auto) with_guard(TArgTuple&& guardCtorArgs, TF&& f) { make_from_tuple<detail::my_guard>(std::forward<TArgTuple>(guardCtorArgs)); f(); }
Использование:
with_guard(std::forward_as_tuple(some_mutex), [&] { // ... });
Этот обходной путь не работает, если инициализация класса защиты имеет "свободный" синтаксис:
{ auto _ = guard_creator() .some_setting(1) .some_setting(2) .create(); }
Есть ли лучшая альтернатива? У меня есть доступ к функциям C ++ 17.
lock_guard
существует и почему он должен оставаться в живых, пока сохраняется область, которую он защищает. попытки добиться этого через API или внутреннюю реализацию просто избыточны. - person David Haim   schedule 30.11.2016lock_guard
. Я работал над генерацией некоторой асинхронной цепочки без выделения памяти с плавным синтаксисом, где очень естественно иметь анонимные цепочки. Но имя все равно нужно, иначе хранилище для цепочки умирает слишком быстро. Это не так очевидно, какlock_guard
, и я бы хотел предотвратить эту ошибку. - person Vittorio Romeo   schedule 30.11.2016std::async
+future::then
с выделенным стеком? - person David Haim   schedule 30.11.2016make_lock_guard
до C ++ 17. Одна из возможностей - принудительно использовать функциюmake_
, а затем пометить ее[[nodiscard]]
. - person T.C.   schedule 30.11.2016