Recently I tried to reinvent scope guard via 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 () (pointer 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;
}
Such an approach works fine for simple pointer to free function void f() { std::cout << 4 << std::endl; } passed to make_scope_guard, but not for any lambda passed to make_scope_guard.
This is due to an abundance of ... = pointer() into the std::unique_ptr definition (function default parameter, defaulting data memebers etc), but I can't find the DefaultConstructible requirement for pointer into this article.
Is it mandatory, that the pointer should match the std::is_default_constructible requirement?
It tested against libc++ and against libstdc++ using not too old clang++ -std=gnu++1z.
Seems, there should be language extension for lambdas: if auto l = [] {}; then using L = decltype(l) is equivalent to struct L { constexpr void operator () () const noexcept { ; } }, isn't it?
Aucun commentaire:
Enregistrer un commentaire