vendredi 31 juillet 2015

unique_ptr and default constructible pointer

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