Skip to content

Instantly share code, notes, and snippets.

@jeffersonfr
Last active February 16, 2023 12:22
Show Gist options
  • Save jeffersonfr/60f8a3e295d14675d511a477b0d4b8a7 to your computer and use it in GitHub Desktop.
Save jeffersonfr/60f8a3e295d14675d511a477b0d4b8a7 to your computer and use it in GitHub Desktop.
Dependency injection
#include <iostream>
#include <type_traits>
#include <tuple>
#include <memory>
template <typename T, typename ...Args>
T inject(Args ...args) {
if constexpr (!std::is_pointer_v<T>) {
return T{std::forward<Args>(args)...};
} else {
using type = typename std::pointer_traits<T>::element_type;
return new type{std::forward<Args>(args)...};
}
}
template <typename ...Args>
struct get {
get(Args ...args): mArgs{args...} {
}
template <typename T>
operator T () {
return std::apply(::inject<T, Args...>, mArgs);
}
template <typename T>
operator std::shared_ptr<T> () {
T *value = std::apply(::inject<T*, Args...>, mArgs);
std::shared_ptr<T> valuePtr{value};
return valuePtr;
}
template <typename T>
operator std::unique_ptr<T> () {
T *value = std::apply(::inject<T*, Args...>, mArgs);
std::unique_ptr<T> valuePtr{value};
return valuePtr;
}
private:
std::tuple<Args...> mArgs;
};
// ----------------------- tests
struct DefaultConstructor {
DefaultConstructor() {
std::cout << "DefaultConstructor\n";
}
};
struct NoDefaultConstructor {
NoDefaultConstructor(int i, char const *s) {
std::cout << "NoDefaultConstructor: " << i << ", " << s << "\n";
}
};
template <>
NoDefaultConstructor inject(int i, char const *s) {
std::cout << "inject<custom injection>: " << i << ", " << s << "\n";
return {i*i, s};
}
void sample(int primitiveType = get{42}, DefaultConstructor defaultConstructor = get{}, NoDefaultConstructor noDefaultConstructor = get{42, "jeff"}) {
}
void sample_ptr(int *primitiveType = get{42}, DefaultConstructor *defaultConstructor = get{}, NoDefaultConstructor *noDefaultConstructor = get{42, "jeff"}) {
}
void sample_shared(std::shared_ptr<int> primitiveType = get{42}, std::shared_ptr<DefaultConstructor> defaultConstructor = get{}, std::shared_ptr<NoDefaultConstructor> noDefaultConstructor = get{42, "jeff"}) {
}
void sample_unique(std::unique_ptr<int> primitiveType = get{42}, std::shared_ptr<DefaultConstructor> defaultConstructor = get{}, std::shared_ptr<NoDefaultConstructor> noDefaultConstructor = get{42, "jeff"}) {
}
int main() {
sample();
sample_ptr();
sample_shared();
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment