unique_ptr, default_delete und allocator



  • Hi!

    Ausgangslage:

    class foobar { ... };
    
    std::unique_ptr<foobar> factory() {
       return new foobar;
    }
    

    Ich möchte dem Nutzer nun Kontrolle darüber geben, wie/wo der Speicher für eine foobar-Instanz angelegt werden soll. Am liebsten hätte ich so etwas in der Art:

    template <template <typename> class Alloc>
    std::unique_ptr<foobar, std::allocator_traits<Alloc<foobar>>::deleter_type> factory(Alloc<foobar>& a) {
       using traits = std::allocator_traits<Alloc<foobar>>;
       auto mem = traits::allocate(a, 1);
       traits::construct(a, mem);
       return { mem, traits::deleter_type(a) };
    }
    

    Ich suche quasi irgendeinen Zusammenhang zwischen einem Allokator und einem Deleter, hier hypothetisch deleter_type, der bei std::allocator der std::default_delete wäre. Gibt es da irgendeine schöne Lösung, ohne dass man der Factory explizit einen Allocator nur für das Anfordern und einen Deleter für das Freigeben von Speicher übergeben muss?


  • Mod

    Der einem Allokator entsprechende Deleter ist mittels deallocate und destroy zu implementieren. In C++14 könnte das so aussehen:

    template <typename Alloc>
    auto factory(Alloc&& a) {
        using traits = std::allocator_traits<Alloc>;
        static_assert(std::is_same<typename traits::value_type, foobar>{}, "Invalid allocator!");
        auto del = [a = std::forward<Alloc>(a)] (auto p) mutable {
            traits::destroy(a, p);
            traits::deallocate(a, p, 1);
        };
        auto mem = traits::allocate(a, 1);
        try {traits::construct(a, mem);}
        catch (...) {
            traits::deallocate(a, mem, 1);
            throw;}
        return std::unique_ptr<typename traits::value_type, decltype(del)>{mem, std::move(del)};
    }
    

    (ungetestet)


Log in to reply