防止用户创建类的未命名实例 [英] Preventing users from creating unnamed instances of a class

查看:83
本文介绍了防止用户创建类的未命名实例的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

对于许多 RAII后卫 类,将其实例化为匿名变量根本没有任何意义:

For many RAII "guard" classes, being instantiated as anonymous variables does not make sense at all:

{
    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.
}

来自这篇文章


C ++中的匿名变量具有表达式范围,这意味着它们将在创建它们的表达式的末尾销毁。

Anonymous variables in C++ have "expression scope", meaning they are destroyed at the end of the expression in which they are created.






有什么方法可以防止用户实例化它们而没有名称吗? (预防可能太强大了-很难也是可以接受的。)

我可以想到两种可能的解决方法,但是它们在使用该类时引入了语法开销:

I can think of two possible workarounds, but they introduce syntactical overhead in the use of the class:


  1. 将类隐藏在详细信息命名空间中,并提供一个宏。

  1. Hide the class in a detail namespace and provide a macro.

namespace detail
{
    class my_guard { /* ... */ };
};

#define SOME_LIB_MY_GUARD(...) \
    detail::my_guard MY_GUARD_UNIQUE_NAME(__LINE__) {__VA_ARGS__}

这是有效的,但 hackish

仅允许用户通过高阶函数使用防护装置。

Only allow the user to use the guard through an higher-order function.

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), [&]
{
    // ...
});

当防护类的初始化具有流利语法时,此解决方法不起作用:

This workaround does not work when the initialization of the guard class has "fluent" syntax:

{
    auto _ = guard_creator()
                 .some_setting(1)
                 .some_setting(2)
                 .create();
}


有没有更好的选择替代?我可以使用C ++ 17功能。

Is there any better alternative? I have access to C++17 features.

推荐答案

我想到的唯一明智的方法是让用户通过结果 guard_creator :: create 到某些 guard_activator 的过程,该过程以左值引用作为参数。

The only sensible way I think about is to make the user pass the result of guard_creator::create to some guard_activator which takes a lvalue-reference as a parameter.

这样,类的用户只能用名称(大多数开发人员会使用的明智选项)创建对象,或者使用 new 然后取消引用(疯狂的选择)

this way, the user of the class has no way but either create the object with a name (the sane option that most developers will do), or new it then dereference (insane options)

例如,您在注释中说,您正在使用非分配异步链创建器。我可以考虑使用如下所示的API:

for example, you said in the comments you work on a non allocating asynchronous chain creator. I can think on an API which looks like this:

auto token = monad_creator().then([]{...}).then([]{...}).then([]{...}).create();
launch_async_monad(token); //gets token as Token&, the user has no way BUT create this object with a name 

这篇关于防止用户创建类的未命名实例的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆