Skip to content

Compilation error when using registerFactory: use of deleted function #126

@dfontenot

Description

@dfontenot

I'm running into an issue with Fruit 3.6.0 in which I run into a compilation error when using Fruit. I've distilled down my project into the following single file:

#include <iostream>
#include <functional>
#include <memory>
#include <utility>
#include "fruit/fruit.h"

using namespace fruit;
using namespace std;

class Qux {
public:
    void test() {
        cout << "Qux" << endl;
    }
};

class Bar {
public:
    virtual ~Bar() {}
    virtual void test() = 0;
};

class BarImpl : public Bar {
    unique_ptr<Qux> ptr_;
public:
    //BarImpl(unique_ptr<Qux>&& ptr) : ptr_(move(ptr)) {}
    BarImpl(unique_ptr<Qux> ptr) : ptr_(move(ptr)) {}
    BarImpl(BarImpl&& b) : ptr_(move(b.ptr_)) {}

    void test() override {
        cout << "BarImpl" << endl;
        ptr_->test();
    }
};

using BarFactory = function<unique_ptr<Bar>(unique_ptr<Qux>)>;

Component<BarFactory> getBarFactoryComponent() {
    return createComponent()
        .registerFactory<unique_ptr<Bar>(Assisted<unique_ptr<Qux> >)>(
                [](unique_ptr<Qux> ptr) {
                    BarImpl* b = new BarImpl(move(ptr));
                    return unique_ptr<Bar>(move(b));
                });
}

class Foo {
public:
    virtual void test() = 0;
    virtual ~Foo() {}
};

class FooImpl : public Foo {
    BarFactory& factory_;
public:
    INJECT(FooImpl(BarFactory& factory)) : factory_(factory) {}

    void test() override {
        cout << "FooImpl" << endl;
        auto bar_ptr = factory_(make_unique<Qux>());
        bar_ptr->test();
    }
};

Component<Foo> getFooComponent() {
    return createComponent().install(getBarFactoryComponent).bind<Foo, FooImpl>();
}

int main(int argc, char** argv) {
    Injector<Foo> injector(getFooComponent);
    Foo& instance = injector.get<Foo&>();

    instance.test();
    return 0;
}
In file included from /home/me/.conan/data/fruit/3.6.0/_/_/package/99fe6edc64c98b6ead2c33cb2b0bf89b59d7f7ce/include/fruit/component.h:25,
                 from /home/me/.conan/data/fruit/3.6.0/_/_/package/99fe6edc64c98b6ead2c33cb2b0bf89b59d7f7ce/include/fruit/fruit.h:27,
                 from main.cpp:5:
/home/me/.conan/data/fruit/3.6.0/_/_/package/99fe6edc64c98b6ead2c33cb2b0bf89b59d7f7ce/include/fruit/impl/component_functors.defn.h: In instantiation of ‘Arg fruit::impl::meta::GetAssistedArg<numAssistedBefore, numNonAssistedBefore, fruit::Assisted<Arg> >::operator()(InjectedArgsTuple&, UserProvidedArgsTuple&) [with InjectedArgsTuple = std::tuple<>; UserProvidedArgsTuple = std::tuple<std::unique_ptr<Qux, std::default_delete<Qux> >&>; int numAssistedBefore = 0; int numNonAssistedBefore = 0; Arg = std::unique_ptr<Qux>]’:
/home/me/.conan/data/fruit/3.6.0/_/_/package/99fe6edc64c98b6ead2c33cb2b0bf89b59d7f7ce/include/fruit/impl/component_functors.defn.h:88:24:   recursively required from ‘void fruit::impl::meta::Compose2ComponentFunctors::apply<F1, F2>::type::apply<Comp>::Op::operator()(fruit::impl::FixedSizeVector<fruit::impl::ComponentStorageEntry>&) [with Comp = fruit::impl::meta::Comp<fruit::impl::meta::Vector<>, fruit::impl::meta::Vector<>, fruit::impl::meta::Vector<>, fruit::impl::meta::Vector<>, fruit::impl::meta::Vector<>, fruit::impl::meta::EmptyList>; F1 = fruit::impl::meta::ComponentFunctor::apply<fruit::impl::meta::RegisterFactory, fruit::impl::meta::Type<std::unique_ptr<Bar, std::default_delete<Bar> >(fruit::Assisted<std::unique_ptr<Qux, std::default_delete<Qux> > >)>, fruit::impl::meta::Type<getBarFactoryComponent()::<lambda(std::unique_ptr<Qux, std::default_delete<Qux> >)> > >::type; F2 = fruit::impl::meta::ProcessDeferredBindings]’
/home/me/.conan/data/fruit/3.6.0/_/_/package/99fe6edc64c98b6ead2c33cb2b0bf89b59d7f7ce/include/fruit/impl/component_functors.defn.h:88:24:   required from ‘void fruit::impl::meta::Compose2ComponentFunctors::apply<F1, F2>::type::apply<Comp>::Op::operator()(fruit::impl::FixedSizeVector<fruit::impl::ComponentStorageEntry>&) [with Comp = fruit::impl::meta::Comp<fruit::impl::meta::Vector<>, fruit::impl::meta::Vector<>, fruit::impl::meta::Vector<>, fruit::impl::meta::Vector<>, fruit::impl::meta::Vector<>, fruit::impl::meta::EmptyList>; F1 = fruit::impl::meta::Compose2ComponentFunctors::apply<fruit::impl::meta::ComponentFunctor::apply<fruit::impl::meta::RegisterFactory, fruit::impl::meta::Type<std::unique_ptr<Bar, std::default_delete<Bar> >(fruit::Assisted<std::unique_ptr<Qux, std::default_delete<Qux> > >)>, fruit::impl::meta::Type<getBarFactoryComponent()::<lambda(std::unique_ptr<Qux, std::default_delete<Qux> >)> > >::type, fruit::impl::meta::ProcessDeferredBindings>::type; F2 = fruit::impl::meta::ComponentFunctor::apply<fruit::impl::meta::ConvertComponent, fruit::impl::meta::Comp<fruit::impl::meta::Vector<>, fruit::impl::meta::Vector<fruit::impl::meta::Type<std::function<std::unique_ptr<Bar, std::default_delete<Bar> >(std::unique_ptr<Qux, std::default_delete<Qux> >)> > >, fruit::impl::meta::Vector<fruit::impl::meta::Type<std::function<std::unique_ptr<Bar, std::default_delete<Bar> >(std::unique_ptr<Qux, std::default_delete<Qux> >)> > >, fruit::impl::meta::Vector<fruit::impl::meta::Pair<fruit::impl::meta::Type<std::function<std::unique_ptr<Bar, std::default_delete<Bar> >(std::unique_ptr<Qux, std::default_delete<Qux> >)> >, fruit::impl::meta::Vector<> > >, fruit::impl::meta::Vector<>, fruit::impl::meta::EmptyList> >::type]’
/home/me/.conan/data/fruit/3.6.0/_/_/package/99fe6edc64c98b6ead2c33cb2b0bf89b59d7f7ce/include/fruit/impl/component.defn.h:66:7:   required from ‘fruit::Component<Types>::Component(fruit::PartialComponent<Bindings ...>&&) [with Bindings = {fruit::impl::RegisterFactory<std::unique_ptr<Bar, std::default_delete<Bar> >(fruit::Assisted<std::unique_ptr<Qux, std::default_delete<Qux> > >), getBarFactoryComponent()::<lambda(std::unique_ptr<Qux, std::default_delete<Qux> >)> >}; Params = {std::function<std::unique_ptr<Bar, std::default_delete<Bar> >(std::unique_ptr<Qux, std::default_delete<Qux> >)>}]’
main.cpp:49:18:   required from here
/home/me/.conan/data/fruit/3.6.0/_/_/package/99fe6edc64c98b6ead2c33cb2b0bf89b59d7f7ce/include/fruit/impl/component_functors.defn.h:405:58: error: use of deleted function ‘std::unique_ptr<_Tp, _Dp>::unique_ptr(const std::unique_ptr<_Tp, _Dp>&) [with _Tp = Qux; _Dp = std::default_delete<Qux>]’
  405 |     return std::get<numAssistedBefore>(user_provided_args);
      |                                                          ^
In file included from /usr/include/c++/9/memory:80,
                 from main.cpp:3:
/usr/include/c++/9/bits/unique_ptr.h:414:7: note: declared here
  414 |       unique_ptr(const unique_ptr&) = delete;
      |       ^~~~~~~~~~

I also attempted to de-fruit-ify the library the best I could, and I was able to get a working binary from it:


#include <iostream>
#include <functional>
#include <memory>
#include <utility>

using namespace std;

class Qux {
public:
    void test() {
        cout << "Qux" << endl;
    }
};

class Bar {
public:
    virtual ~Bar() {}
    virtual void test() = 0;
};

class BarImpl : public Bar {
    unique_ptr<Qux> ptr_;
public:
    BarImpl(unique_ptr<Qux> ptr) : ptr_(move(ptr)) {}
    BarImpl(BarImpl&& b) : ptr_(move(b.ptr_)) {}

    void test() override {
        cout << "BarImpl" << endl;
        ptr_->test();
    }
};

using BarFactory = function<unique_ptr<Bar>(unique_ptr<Qux>)>;

BarFactory getBarFactory() {
    return [](unique_ptr<Qux> ptr) {
        BarImpl* b = new BarImpl(move(ptr));
        return unique_ptr<Bar>(move(b));
    };
}

class Foo {
public:
    virtual void test() = 0;
    virtual ~Foo() {}
};

class FooImpl : public Foo {
    BarFactory& factory_;
public:
    FooImpl(BarFactory& factory) : factory_(factory) {}

    void test() override {
        cout << "FooImpl" << endl;
        auto bar_ptr = factory_(make_unique<Qux>());
        bar_ptr->test();
    }
};

int main(int argc, char** argv) {

    BarFactory factory = getBarFactory();
    Foo* instance = new FooImpl(factory);

    instance->test();
    return 0;
}

Would you be able to provide any guidance as to if I'm misusing registerFactory? Or was there an error in my code that was not properly translated when it was converted into non-fruit code? My c++ is definitely a rusty, but it seems as though the lambda that the compiler is complaining about is the same between both versions.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions