Для многого 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.
}
От 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.
Я думаю, что вы просите в неправильном направлении. Разработчики C++ должны понимать, почему существует 'lock_guard', и почему он должен оставаться в живых, пока область, которую он защищает, стоит. попытка принудительного применения этого через API или внутренняя реализация просто избыточна. –
@ Danh: ответ другого вопроса - это мой «макрос» обходной путь. Не могли бы вы рассмотреть вопрос о повторном открытии этого вопроса, если я сделаю более очевидным, что я ищу решение на основе макросов? @ Давид: для примера «lock_guard» я согласен. Я работал над некоторой цепочкой генерации async без выделения с «беглым» синтаксисом, хотя, где очень естественно иметь анонимные цепочки. Но вы все равно нуждаетесь в имени, иначе хранилище для сети быстро погибает. Это не так очевидно, как «lock_guard», и я бы хотел предотвратить эту ошибку. –
@VittorioRomeo В этом вопросе есть и другие ответы. И, ИМХО, если мы можем централизовать все дискуссии об этом в одном месте, это лучше. Во всяком случае, [этот ответ] (http://stackoverflow.com/a/16192104/4115625) выглядит очень интересно – Danh