google / google/fruit

Compilation error when using registerFactory: use of deleted function

Open
#126 22 comments 0 reactions 0 assignees View on GitHub
Dominant language
C++
Stars
1.9k
Forks
202
PR merge metrics
No merged PRs in 30d

Description

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
#include
#include
#include
#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 ptr_;
public:
//BarImpl(unique_ptr&& ptr) : ptr_(move(ptr)) {}
BarImpl(unique_ptr ptr) : ptr_(move(ptr)) {}
BarImpl(BarImpl&& b) : ptr_(move(b.ptr_)) {}

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

using BarFactory = function(unique_ptr)>;

Component getBarFactoryComponent() {
return createComponent()
.registerFactory(Assisted >)>(
[](unique_ptr ptr) {
BarImpl* b = new BarImpl(move(ptr));
return unique_ptr(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());
bar_ptr->test();
}
};

Component getFooComponent() {
return createComponent().install(getBarFactoryComponent).bind();
}

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

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 >::operator()(InjectedArgsTuple&, UserProvidedArgsTuple&) [with InjectedArgsTuple = std::tuple<>; UserProvidedArgsTuple = std::tuple >&>; int numAssistedBefore = 0; int numNonAssistedBefore = 0; Arg = std::unique_ptr]’:
/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::type::apply::Op::operator()(fruit::impl::FixedSizeVector&) [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::EmptyList>; F1 = fruit::impl::meta::ComponentFunctor::apply >(fruit::Assisted > >)>, fruit::impl::meta::Type >)> > >::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::type::apply::Op::operator()(fruit::impl::FixedSizeVector&) [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::EmptyList>; F1 = fruit::impl::meta::Compose2ComponentFunctors::apply >(fruit::Assisted > >)>, fruit::impl::meta::Type >)> > >::type, fruit::impl::meta::ProcessDeferredBindings>::type; F2 = fruit::impl::meta::ComponentFunctor::apply, fruit::impl::meta::Vector >(std::unique_ptr >)> > >, fruit::impl::meta::Vector >(std::unique_ptr >)> > >, fruit::impl::meta::Vector >(std::unique_ptr >)> >, 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::Component(fruit::PartialComponent&&) [with Bindings = {fruit::impl::RegisterFactory >(fruit::Assisted > >), getBarFactoryComponent():: >)> >}; Params = {std::function >(std::unique_ptr >)>}]’
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]’
405 | return std::get(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
#include
#include
#include

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 ptr_;
public:
BarImpl(unique_ptr ptr) : ptr_(move(ptr)) {}
BarImpl(BarImpl&& b) : ptr_(move(b.ptr_)) {}

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

using BarFactory = function(unique_ptr)>;

BarFactory getBarFactory() {
return [](unique_ptr ptr) {
BarImpl* b = new BarImpl(move(ptr));
return unique_ptr(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());
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.

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.