Skip to content

Commit

Permalink
Mark Component's copy constructor, conversion operator and install me…
Browse files Browse the repository at this point in the history
…thod as deprecated. Also add a non-deprecated install method with the same signature as the one in 3.0.0. These changes were backported from master.
  • Loading branch information
poletti-marco committed Jul 15, 2017
1 parent ea82a9c commit 28894a1
Show file tree
Hide file tree
Showing 22 changed files with 406 additions and 120 deletions.
4 changes: 2 additions & 2 deletions examples/annotated_injection/car.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,6 @@ class CarImpl : public Car {
fruit::Component<Car> getCarComponent() {
return fruit::createComponent()
.bind<Car, CarImpl>()
.install(getMainBrakeComponent())
.install(getEmergencyBrakeComponent());
.install(getMainBrakeComponent)
.install(getEmergencyBrakeComponent);
}
2 changes: 1 addition & 1 deletion examples/scaling_doubles/scaler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -40,5 +40,5 @@ class ScalerImpl : public Scaler {
Component<ScalerFactory> getScalerComponent() {
return createComponent()
.bind<Scaler, ScalerImpl>()
.install(getMultiplierComponent());
.install(getMultiplierComponent);
}
2 changes: 1 addition & 1 deletion examples/server/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ int main() {
Injector<Server> injector(getServerComponent());

Server* server(injector);
server->run(getRequestDispatcherComponent());
server->run(getRequestDispatcherComponent);

return 0;
}
4 changes: 2 additions & 2 deletions examples/server/request_dispatcher.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,6 @@ class RequestDispatcherImpl : public RequestDispatcher {
Component<Required<Request, ServerContext>, RequestDispatcher> getRequestDispatcherComponent() {
return createComponent()
.bind<RequestDispatcher, RequestDispatcherImpl>()
.install(getFooHandlerComponent())
.install(getBarHandlerComponent());
.install(getFooHandlerComponent)
.install(getBarHandlerComponent);
}
4 changes: 2 additions & 2 deletions examples/server/server.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,13 +37,13 @@ class ServerImpl : public Server {
}
}

void run(Component<Required<Request, ServerContext>, RequestDispatcher> requestDispatcherComponent) override {
void run(Component<Required<Request, ServerContext>, RequestDispatcher>(*requestDispatcherComponent)()) override {
ServerContext serverContext;
serverContext.startupTime = getTime();

const NormalizedComponent<Required<Request>, RequestDispatcher> requestDispatcherNormalizedComponent(
createComponent()
.install(std::move(requestDispatcherComponent))
.install(requestDispatcherComponent)
.bindInstance(serverContext));

cerr << "Server started." << endl;
Expand Down
3 changes: 2 additions & 1 deletion examples/server/server.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,8 @@

class Server {
public:
virtual void run(fruit::Component<fruit::Required<Request, ServerContext>, RequestDispatcher> requestDispatcherComponent) = 0;
virtual void run(
fruit::Component<fruit::Required<Request, ServerContext>, RequestDispatcher>(*)()) = 0;
};

fruit::Component<Server> getServerComponent();
Expand Down
4 changes: 2 additions & 2 deletions examples/simple_injection/checked_incrementer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,6 @@

fruit::Component<Incrementer> getCheckedIncrementerComponent() {
return fruit::createComponent()
.install(getIncrementerImplComponent())
.install(getCheckedAdderComponent());
.install(getIncrementerImplComponent)
.install(getCheckedAdderComponent);
}
4 changes: 2 additions & 2 deletions examples/simple_injection/simple_incrementer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,6 @@

fruit::Component<Incrementer> getSimpleIncrementerComponent() {
return fruit::createComponent()
.install(getIncrementerImplComponent())
.install(getSimpleAdderComponent());
.install(getIncrementerImplComponent)
.install(getSimpleAdderComponent);
}
63 changes: 54 additions & 9 deletions include/fruit/component.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ template <typename... Params>
class Component {
public:
Component(Component&&) = default;
Component(const Component&) = default;
FRUIT_DEPRECATED_DECLARATION(Component(const Component&));

Component& operator=(Component&&) = delete;
Component& operator=(const Component&) = delete;
Expand All @@ -61,7 +61,7 @@ class Component {
* It's provided only for convenience.
*/
template <typename... OtherParams>
Component(Component<OtherParams...> component);
FRUIT_DEPRECATED_DECLARATION(Component(Component<OtherParams...> component));

private:
// Do not use. Use fruit::createComponent() instead.
Expand Down Expand Up @@ -92,8 +92,8 @@ class Component {
*
* fruit::Component<Foo> getFooComponent() {
* return fruit::createComponent()
* .install(getComponent1())
* .install(getComponent2())
* .install(getComponent1)
* .install(getComponent2)
* .bind<Foo, FooImpl>();
* }
*
Expand Down Expand Up @@ -122,8 +122,8 @@ PartialComponent<> createComponent();
*
* fruit::Component<Foo> getFooComponent() {
* return fruit::createComponent()
* .install(getComponent1())
* .install(getComponent2())
* .install(getComponent1)
* .install(getComponent2)
* .bind<Foo, FooImpl>();
* }
*
Expand Down Expand Up @@ -459,16 +459,61 @@ class PartialComponent {
* Example usage:
*
* createComponent()
* .install(getComponent1())
* .install(getComponent2())
* .install(getComponent1)
* .install(getComponent2)
*
* As in the example, the template parameters will be inferred by the compiler, it's not necessary to specify them explicitly.
*
* This supports annotated injection, just wrap the desired types (return type and/or argument types of the signature)
* with fruit::Annotated<> if desired.
*/
template <typename... Params>
PartialComponent<fruit::impl::InstallComponent<Component<Params...>>, Bindings...> install(Component<Params...> component) &&;
FRUIT_DEPRECATED_DECLARATION(
PartialComponent<fruit::impl::InstallComponent<Component<Params...>>, Bindings...>
install(Component<Params...> component) &&
);

/**
* Adds the bindings (and multibindings) in the Component obtained by calling fun(args...) to the current component.
*
* For example, these components:
* Component<Foo> getComponent1();
* Component<Bar> getComponent2(int n, std::string s);
*
* can be installed as:
*
* createComponent()
* // equivalent to install(getComponent1())
* .install(getComponent1)
* // equivalent to install(getComponent2(5, std::string("Hello"))
* .install(getComponent2, 5, std::string("Hello"))
*
* If any `args` are provided, they must be:
* - Copy-constructible
* - Move-constructible
* - Assignable
* - Move-assignable
* - Equality comparable (i.e., operator== must be defined for two values of that type)
* - Hashable (i.e., std::hash must be defined for values of that type)
*
* Note that this only applies to `args`. E.g. in the example above `int` and `std::string` must satisfy this
* requirement (and they do), but `Foo` and `Bar` don't need to.
*
* A lambda with no captures can also be used as the first argument, for example:
*
* createComponent()
* .install([]() {return getComponent1();})
* .install([](int n, std::string s) {return getComponent2(n, s);}, 5, std::string("Hello"))
*
* These two install() calls are equivalent to the previous ones.
*
* As in the example, the template parameters for this method will be inferred by the compiler, it's not necessary to
* specify them explicitly.
*/
template <typename OtherComponent, typename... Args>
PartialComponent<fruit::impl::InstallComponent<OtherComponent>, Bindings...> install(
OtherComponent(*)(Args...),
Args... args) &&;

private:
template <typename... OtherBindings>
Expand Down
48 changes: 46 additions & 2 deletions include/fruit/impl/component.defn.h
Original file line number Diff line number Diff line change
Expand Up @@ -64,9 +64,14 @@ inline Component<Params...>::Component(PartialComponent<Bindings...> component)
Op()(storage);
}

template <typename... Params>
inline FRUIT_DEPRECATED_DEFINITION(Component<Params...>::Component(const Component& other))
: storage(other.storage) {
}

template <typename... Params>
template <typename... OtherParams>
inline Component<Params...>::Component(Component<OtherParams...> component)
inline FRUIT_DEPRECATED_DEFINITION(Component<Params...>::Component(Component<OtherParams...> component))
: Component(fruit::createComponent().install(component)) {
}

Expand Down Expand Up @@ -221,14 +226,53 @@ PartialComponent<Bindings...>::registerFactory(Lambda) && {
template <typename... Bindings>
template <typename... OtherCompParams>
inline PartialComponent<fruit::impl::InstallComponent<Component<OtherCompParams...>>, Bindings...>
PartialComponent<Bindings...>::install(Component<OtherCompParams...> component) && {
FRUIT_DEPRECATED_DEFINITION(PartialComponent<Bindings...>::install(Component<OtherCompParams...> component)) && {
using Op = OpFor<fruit::impl::InstallComponent<Component<OtherCompParams...>>>;
(void)typename fruit::impl::meta::CheckIfError<Op>::type();

storage.install(std::move(component.storage));
return {std::move(storage)};
}

template <typename T>
FRUIT_ALWAYS_INLINE
inline int checkAcceptableComponentInstallArg() {
// This lambda checks that the required operations on T exist.
// Note that the lambda is never actually executed.
auto checkRequirements = [](const T& constRef, T value) {
T x1(constRef);
T x2(std::move(value));
x1 = constRef;
x2 = std::move(value);
bool b = (constRef == constRef);
std::size_t h = std::hash<T>()(constRef);
(void)x1;
(void)x2;
(void)b;
(void)h;
};
(void)checkRequirements;
return 0;
}

template <typename... Bindings>
template <typename OtherComponent, typename... Args>
inline PartialComponent<fruit::impl::InstallComponent<OtherComponent>, Bindings...>
PartialComponent<Bindings...>::install(
OtherComponent(*f)(Args...),
Args... args) && {
using IntCollector = int[];
(void)(IntCollector{0, checkAcceptableComponentInstallArg<Args>()...});

using Op = OpFor<fruit::impl::InstallComponent<OtherComponent>>;
(void)typename fruit::impl::meta::CheckIfError<Op>::type();

OtherComponent component = f(std::move(args)...);

storage.install(std::move(component.storage));
return {std::move(storage)};
}

} // namespace fruit

#endif // FRUIT_COMPONENT_DEFN_H
18 changes: 0 additions & 18 deletions tests/test_bind_instance.py
Original file line number Diff line number Diff line change
Expand Up @@ -107,24 +107,6 @@ def test_success_two_explicit_type_arguments(XAnnot, XRefAnnot):
'''
expect_success(COMMON_DEFINITIONS, source, locals())

@pytest.mark.parametrize('XAnnot', [
'X',
'fruit::Annotated<Annotation1, X>',
])
def test_mismatched_type_arguments(XAnnot):
source = '''
struct X {};
fruit::Component<> getComponent(int& n) {
return fruit::createComponent()
.bindInstance<XAnnot, int>(n);
}
'''
expect_success(
COMMON_DEFINITIONS,
source,
locals())

@pytest.mark.parametrize('BaseAnnot,BasePtrAnnot', [
('Base', 'Base*'),
('fruit::Annotated<Annotation1, Base>', 'fruit::Annotated<Annotation1, Base*>'),
Expand Down
23 changes: 4 additions & 19 deletions tests/test_bind_interface.py
Original file line number Diff line number Diff line change
Expand Up @@ -108,21 +108,6 @@ def test_bound_chain_ok():
'''
expect_success(COMMON_DEFINITIONS, source)

def test_bind_non_normalized_types_error():
source = '''
struct X {};
struct Y : public std::shared_ptr<X> {};
fruit::Component<> getComponent() {
return fruit::createComponent()
.bind<std::shared_ptr<X>, Y>();
}
'''
expect_success(
COMMON_DEFINITIONS,
source)

def test_bind_factory_no_args():
source = '''
struct X {
Expand All @@ -145,7 +130,7 @@ def test_bind_factory_no_args():
fruit::Component<Factory<X>> getComponent() {
return fruit::createComponent()
.install(getYComponent())
.install(getYComponent)
.bind<X, Y>();
}
Expand Down Expand Up @@ -180,7 +165,7 @@ def test_bind_factory_no_args_invalid_unique_ptr():
fruit::Component<Factory<X>> getComponent() {
return fruit::createComponent()
.install(getYComponent())
.install(getYComponent)
.bind<X, Y>();
}
Expand Down Expand Up @@ -216,7 +201,7 @@ def test_bind_factory_1_arg():
fruit::Component<Factory<X>> getComponent() {
return fruit::createComponent()
.install(getYComponent())
.install(getYComponent)
.bind<X, Y>();
}
Expand Down Expand Up @@ -252,7 +237,7 @@ def test_bind_factory_2_arg():
fruit::Component<Factory<X>> getComponent() {
return fruit::createComponent()
.install(getYComponent())
.install(getYComponent)
.bind<X, Y>();
}
Expand Down
Loading

0 comments on commit 28894a1

Please sign in to comment.