c++ - 防止用户创建类的未命名实例

标签 c++ c++17 raii

<分区>

对于许多 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 :

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


有什么方法可以防止用户在没有名字的情况下实例化它们吗? (“防止”可能太强了 - “让它变得非常困难”也是可以接受的)。 em>

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

  1. 将类隐藏在 detail 命名空间中并提供一个宏。

    namespace detail
    {
        class my_guard { /* ... */ };
    };
    
    #define SOME_LIB_MY_GUARD(...) \
        detail::my_guard MY_GUARD_UNIQUE_NAME(__LINE__) {__VA_ARGS__}
    

    这有效,但是hackish

  2. 只允许用户通过高阶函数使用守卫。

    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 功能。

最佳答案

我想到的唯一明智的方法是让用户将 guard_creator::create 的结果传递给某个 guard_activator,它采用左值引用作为参数。

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

例如,您在评论中说您在处理非分配异步链创建器。我可以考虑一个如下所示的 API:

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 

关于c++ - 防止用户创建类的未命名实例,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55919321/

相关文章:

c++ - 这个 reinterpret_cast 原则上和/或实践上有问题吗?

c++ - 由于抛出异常而检测析构函数何时运行?

c++ - Google Test 中的 RAII 内存损坏

c++ - 为什么 c++ 将大数四舍五入到 ceil 并将小数四舍五入到地板

c++ - 在 C++ 中以字节 block 的形式读取和写入文件

c++ - 如何在 c++ "XY:56:21AM"中从这个字符串中分离出 HH、MM、SS 和 merdian?以下程序出现段错误

c++ - 为什么 std::optional<int> 的构造比 std::pair<int, bool> 更昂贵?

c# - 在 C# 中实现 RAII

c++ - 从代码中删除 SAL 注释是否安全?

c++ - 在 OpenGL 中使用 for 循环创建数组