unique_ptr和默认的可构造指针

时间:2015-07-31 15:18:44

标签: c++ c++11 lambda c++14 unique-ptr

最近我尝试通过std::unique_ptr重新发明范围保护注意删除有成员typedef pointer - 是std::unique_ptr)的特殊处理案例:

#include <type_traits>
#include <utility>
#include <memory>
#include <iostream>

#include <cstdlib>
#include <cassert>

namespace
{

template< typename lambda >
auto
make_scope_guard(lambda && _lambda)
{
    struct lambda_caller
    {

        using pointer = std::decay_t< lambda >;

        void
        operator () (lambda & l) const noexcept
        {
            std::forward< lambda >(l)();
        }

    };
    return std::unique_ptr< std::decay_t< lambda >, lambda_caller >(std::forward< lambda >(_lambda));
}

}

int
main()
{
    std::cout << 1 << std::endl;
    {
        std::cout << 2 << std::endl;
        [[gnu::unused]] auto && guard_ = make_scope_guard([&] { std::cout << __PRETTY_FUNCTION__ << std::endl; });
        std::cout << 3 << std::endl;
    }
    std::cout << 5 << std::endl;
    return EXIT_SUCCESS;
}

这种方法适用于传递给void f() { std::cout << 4 << std::endl; }的自由函数make_scope_guard的简单指针,但不适用于传递给make_scope_guard的任何lambda。

这是由于... = pointer()定义中的std::unique_ptr丰富(函数默认参数,默认数据成员等),但我无法找到 DefaultConstructible 要求pointer进入article

是强制性的,pointer是否应符合std::is_default_constructible要求?

使用不太旧的libc++libstdc++clang++ -std=gnu++1z进行了测试。

似乎,lambdas应该有语言扩展:如果auto l = [/* possible capture list */] (Args...) { /* code */; };那么using L = decltype(l);相当于某些struct L { constexpr void operator () (Args...) const noexcept { ; } };的{​​{1}},那么它不是吗?

其他

将以下 DefaultConstructible 类的实例Args...提供给D{},需要在上下文make_scope_guard(D{})中取消注释已注释掉的代码,其中if (p) { ...属于p类型:

D

1 个答案:

答案 0 :(得分:4)

mysite.com/profile/仍是指针。你不能把一个lambda钉进去。来自[unique.ptr]:

  

唯一指针是拥有另一个对象并通过指针管理该另一个对象的对象。   更准确地说,唯一指针是一个对象,它将指针存储到第二个对象p并将被处置   p当你自己被摧毁时

     

[...]

     

此外, u 可以根据请求将所有权转移到另一个唯一指针 u2 。完成后   这样的转移,以下后置条件成立:[...] u.p 等于unique_ptr

lambda不是指针。 lambda不能等于nullptr

那就是说,你已经在制作自己的本地结构了,为什么不使用那个来做RAII范围而不是推迟到nullptr呢?这似乎是一个hack充其量,并需要更多的代码来启动。你可以改为:

unique_ptr

如果您需要支持template< typename lambda > auto make_scope_guard(lambda && _lambda) { struct lambda_caller { lambda _lambda; ~lambda_caller() { _lambda(); } }; return lambda_caller{std::forward<lambda>(_lambda)}; } ,可以将release包裹在_lambda内,以便boost::optional成为:

lambda_caller