Skip to content

Commit

Permalink
nested resolution II
Browse files Browse the repository at this point in the history
  • Loading branch information
romanpauk committed Nov 10, 2024
1 parent bc19841 commit 6546358
Show file tree
Hide file tree
Showing 18 changed files with 509 additions and 358 deletions.
21 changes: 11 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -182,10 +182,10 @@ a list initialization, going from a pre-configured number of arguments down to
zero. In a case the constructor is not determined, compile assert occurs. This
factory type is a default one so it does not have to be specified.

<!-- { include("examples/factory_constructor.cpp", scope="////") -->
<!-- { include("examples/factory_constructor_deduction.cpp", scope="////") -->

Example code included from
[examples/factory_constructor.cpp](examples/factory_constructor.cpp):
[examples/factory_constructor_deduction.cpp](examples/factory_constructor_deduction.cpp):

```c++
struct A {
Expand All @@ -198,25 +198,26 @@ container.register_type<scope<external>, storage<double>>(1.1);

// Constructor with a highest arity will be used (factory<> is deduced
// automatically)
container
.register_type<scope<unique>, storage<A> /*, factory<constructor<A>> */>();
container.register_type<scope<unique>,
storage<A> /*, factory<constructor_deduction<A>> */>();
```
<!-- } -->
See [dingo/factory/constructor.h](include/dingo/factory/constructor.h) for
details.
See
[dingo/factory/constructor_deduction.h](include/dingo/factory/constructor_deduction.h)
for details.
##### Concrete Constructor Factory
In a case an automatic deduction fails due to an ambiguity, it is possible to
override the constructor by specifying an constructor overload that will be
used.
<!-- { include("examples/factory_constructor_concrete.cpp", scope="////") -->
<!-- { include("examples/factory_constructor.cpp", scope="////") -->
Example code included from
[examples/factory_constructor_concrete.cpp](examples/factory_constructor_concrete.cpp):
[examples/factory_constructor.cpp](examples/factory_constructor.cpp):
```c++
struct A {
Expand Down Expand Up @@ -244,10 +245,10 @@ details.
Static function factory allows a static function to be used for an instance
creation.

<!-- { include("examples/factory_static_function.cpp", scope="////") -->
<!-- { include("examples/factory_function.cpp", scope="////") -->

Example code included from
[examples/factory_static_function.cpp](examples/factory_static_function.cpp):
[examples/factory_function.cpp](examples/factory_function.cpp):

```c++
// Declare struct A that has an inaccessible constructor
Expand Down
4 changes: 2 additions & 2 deletions examples/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ add_example(collection.cpp)
add_example(construct.cpp)
add_example(factory_callable.cpp)
add_example(factory_constructor.cpp)
add_example(factory_constructor_concrete.cpp)
add_example(factory_static_function.cpp)
add_example(factory_constructor_deduction.cpp)
add_example(factory_function.cpp)
add_example(index.cpp)
add_example(invoke.cpp)
add_example(message_processing.cpp)
Expand Down
21 changes: 11 additions & 10 deletions examples/factory_constructor.cpp
Original file line number Diff line number Diff line change
@@ -1,30 +1,31 @@
#include <dingo/container.h>
#include <dingo/storage/external.h>
#include <dingo/storage/unique.h>
//
// This file is part of dingo project <https://github.com/romanpauk/dingo>
//
// See LICENSE for license and copyright information
// SPDX-License-Identifier: MIT
//

#include <dingo/container.h>
#include <dingo/storage/external.h>
#include <dingo/storage/unique.h>

////
struct A {
A(int); // Definition is not required as constructor is not called
A(double, double) {} // Definition is required as constructor is called
A(int); // Definition is not required as constructor is not called
A(double) {} // Definition is required as constructor is called
};

////

int main() {
using namespace dingo;
////
container<> container;
container.register_type<scope<external>, storage<double>>(1.1);

// Constructor with a highest arity will be used (factory<> is deduced
// automatically)
container.register_type<scope<unique>,
storage<A> /*, factory<constructor<A>> */>();
// Register class A that will be constructed using manually selected
// A(double) constructor. Manually disambiguation is required to avoid
// compile time assertion
container.register_type<scope<unique>, storage<A>,
factory<constructor<A(double)>>>();
////
}
Original file line number Diff line number Diff line change
@@ -1,31 +1,30 @@
#include <dingo/container.h>
#include <dingo/storage/external.h>
#include <dingo/storage/unique.h>
//
// This file is part of dingo project <https://github.com/romanpauk/dingo>
//
// See LICENSE for license and copyright information
// SPDX-License-Identifier: MIT
//

#include <dingo/container.h>
#include <dingo/storage/external.h>
#include <dingo/storage/unique.h>

////
struct A {
A(int); // Definition is not required as constructor is not called
A(double) {} // Definition is required as constructor is called
A(int); // Definition is not required as constructor is not called
A(double, double) {} // Definition is required as constructor is called
};

////

int main() {
using namespace dingo;
////
container<> container;
container.register_type<scope<external>, storage<double>>(1.1);

// Register class A that will be constructed using manually selected
// A(double) constructor. Manually disambiguation is required to avoid
// compile time assertion
container.register_type<scope<unique>, storage<A>,
factory<constructor<A(double)>>>();
// Constructor with a highest arity will be used (factory<> is deduced
// automatically)
container.register_type<scope<unique>,
storage<A> /*, factory<constructor_deduction<A>> */>();
////
}
File renamed without changes.
24 changes: 19 additions & 5 deletions include/dingo/class_traits.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ template <typename T> struct class_traits<T&> {
template <typename T> struct class_traits<std::unique_ptr<T>> {
template <typename... Args>
static std::unique_ptr<T> construct(Args&&... args) {
return std::make_unique<T>(std::forward<Args>(args)...);
return std::unique_ptr<T>{new T{std::forward<Args>(args)...}};
}

template <typename... Args>
Expand All @@ -59,7 +59,12 @@ template <typename T> struct class_traits<std::unique_ptr<T>> {
template <typename T> struct class_traits<std::shared_ptr<T>> {
template <typename... Args>
static std::shared_ptr<T> construct(Args&&... args) {
return std::make_shared<T>(std::forward<Args>(args)...);
// TODO: work around direct-initialization in std::make_shared().
// https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4462.html
if constexpr(std::is_constructible_v<T, Args...>)
return std::make_shared<T>(std::forward<Args>(args)...);
else
return std::shared_ptr<T>{new T{std::forward<Args>(args)...}};
}

template <typename... Args>
Expand All @@ -71,18 +76,27 @@ template <typename T> struct class_traits<std::shared_ptr<T>> {
template <typename T> struct class_traits<std::optional<T>> {
template <typename... Args>
static std::optional<T> construct(Args&&... args) {
return std::make_optional<T>(std::forward<Args>(args)...);
if constexpr(std::is_constructible_v<T, Args...>)
return std::optional<T>{std::in_place, std::forward<Args>(args)...};
else
return std::optional<T>{std::in_place, T{std::forward<Args>(args)...}};
}

template <typename... Args>
static std::optional<T>& construct(std::optional<T>& ptr, Args&&... args) {
ptr.emplace(std::forward<Args>(args)...);
if constexpr (std::is_constructible_v<T, Args...>)
ptr.emplace(std::forward<Args>(args)...);
else
ptr.emplace(T{std::forward<Args>(args)...});
return ptr;
}

template <typename... Args>
static void construct(void* ptr, Args&&... args) {
new (ptr) std::optional<T>{std::in_place, std::forward<Args>(args)...};
if constexpr(std::is_constructible_v<T, Args...>)
new (ptr) std::optional<T>{std::in_place, std::forward<Args>(args)...};
else
new (ptr) std::optional<T>{std::in_place, T{std::forward<Args>(args)...}};
}
};

Expand Down
2 changes: 1 addition & 1 deletion include/dingo/constructor.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,4 @@ template <typename...> struct constructor;
::dingo::constructor<__VA_ARGS__>; \
__VA_ARGS__

} // namespace dingo
} // namespace dingo
11 changes: 6 additions & 5 deletions include/dingo/container.h
Original file line number Diff line number Diff line change
Expand Up @@ -214,7 +214,7 @@ class container : public allocator_base<Allocator> {
return resolve<T, true, false>(context, std::forward<IdType>(id));
}

template <typename T, typename Factory = constructor<decay_t<T>>>
template <typename T, typename Factory = constructor_detection<decay_t<T>>>
T construct(Factory factory = Factory()) {
// TODO: nothrow constructuble
resolving_context context;
Expand Down Expand Up @@ -453,17 +453,18 @@ class container : public allocator_base<Allocator> {
}
}

// If we are trying to construct T& and it is not wrapped in any way
if constexpr (std::is_lvalue_reference_v<T> && std::is_same_v< Type, std::decay_t<T> >) {
// If we are trying to construct T and it is not wrapped in any way
if constexpr (std::is_same_v< Type, std::decay_t<T> >) {
// And it is constructible
using type_constructor = detail::constructor_detection< Type, detail::list_initialization, false >;
using type_detection = detail::reference;
using type_constructor = detail::constructor_detection< Type, type_detection, detail::list_initialization, false >;
if constexpr(type_constructor::valid) {
// TODO: this ends up with gcc 14 stuck in compilation
//register_type< scope<unique>, storage<Type> >();
//return resolve<T, RemoveRvalueReferences, CheckCache>(context);

// Construct temporary through context so it can be referenced
return context.template construct_temporary< Type >(*this);
return context.template construct_temporary< typename annotated_traits<T>::type, type_detection >(*this);
}
}

Expand Down
Loading

0 comments on commit 6546358

Please sign in to comment.