Ori*_*ent 5 c++ lambda unique-ptr c++11 c++14
最近,我试图彻底改造范围后卫通过std::unique_ptr(注:缺失者有成员类型定义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;
}
Run Code Online (Sandbox Code Playgroud)
这种方法适用于void f() { std::cout << 4 << std::endl; }传递给自由函数的简单指针make_scope_guard,但不适用于传递给它的任何lambda make_scope_guard.
这是由于大量的... = pointer()进入std::unique_ptr定义(函数默认参数,默认数据承包商,客人等等),但我不能找到缺省构造的要求对pointer这个文章.
它是强制性的,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 { ; } };于某些Args...,不是吗?
额外:
提供了实例D{}以下的可缺省类make_scope_guard(D{})需要注释的代码中的上下文中未注释if (p) { ...,其中p的类型为D:
struct D { void operator () () const noexcept { std::cout << __PRETTY_FUNCTION__ << std::endl; } /* constexpr operator bool () const { return true; } */ };
Run Code Online (Sandbox Code Playgroud)
Aunique_ptr仍然是一个指针。你不能把 lambda 硬塞进去。来自[unique.ptr]:
唯一指针是一个拥有另一个对象并通过指针管理另一个对象的对象。更准确地说,唯一指针是一个对象 u,它存储指向第二个对象 p 的指针,并且当 u 本身被销毁时将处理 p
[...]
此外,u可以根据请求将所有权转移给另一个唯一指针u2。完成此类传输后,以下后置条件成立: [...] up等于
nullptr
lambda 不是指针。lambda 不能等于nullptr。
也就是说,您已经在创建自己的本地结构,为什么不直接使用它来保护自身的 RAII 范围而不是遵循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)};
}
Run Code Online (Sandbox Code Playgroud)
如果需要支持release,可以将 包裹_lambda起来,boost::optional这样就lambda_caller变成:
struct lambda_caller
{
boost::optional<lambda> _lambda;
~lambda_caller()
{
if (_lambda) {
(*_lambda)();
_lambda = boost::none;
}
}
void release() {
_lambda = boost::none;
}
};
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
229 次 |
| 最近记录: |