#pragma once
#include <memory>
namespace ableton
{
namespace util
{
template <typename T>
struct Injected
{
using type = T;
Injected() = default;
explicit Injected(T t)
: val(std::move(t))
{
}
Injected(const Injected&) = default;
Injected& operator=(const Injected&) = default;
Injected(Injected&& rhs)
: val(std::move(rhs.val))
{
}
Injected& operator=(Injected&& rhs)
{
val = std::move(rhs.val);
return *this;
}
T* operator->() { return &val; }
const T* operator->() const { return &val; }
T& operator*() { return val; }
const T& operator*() const { return val; }
T val;
};
template <typename T>
Injected<T> injectVal(T t)
{
return Injected<T>(std::move(t));
}
template <typename T>
struct Injected<T&>
{
using type = T;
explicit Injected(T& t)
: ref(std::ref(t))
{
}
Injected(const Injected&) = default;
Injected& operator=(const Injected&) = default;
Injected(Injected&& rhs)
: ref(std::move(rhs.ref))
{
}
Injected& operator=(Injected&& rhs)
{
ref = std::move(rhs.ref);
return *this;
}
T* operator->() { return &ref.get(); }
const T* operator->() const { return &ref.get(); }
T& operator*() { return ref; }
const T& operator*() const { return ref; }
std::reference_wrapper<T> ref;
};
template <typename T>
Injected<T&> injectRef(T& t)
{
return Injected<T&>(t);
}
template <typename T>
struct Injected<std::shared_ptr<T>>
{
using type = T;
explicit Injected(std::shared_ptr<T> pT)
: shared(std::move(pT))
{
}
Injected(const Injected&) = default;
Injected& operator=(const Injected&) = default;
Injected(Injected&& rhs)
: shared(std::move(rhs.shared))
{
}
Injected& operator=(Injected&& rhs)
{
shared = std::move(rhs.shared);
return *this;
}
T* operator->() { return shared.get(); }
const T* operator->() const { return shared.get(); }
T& operator*() { return *shared; }
const T& operator*() const { return *shared; }
std::shared_ptr<T> shared;
};
template <typename T>
Injected<std::shared_ptr<T>> injectShared(std::shared_ptr<T> shared)
{
return Injected<std::shared_ptr<T>>(std::move(shared));
}
template <typename T>
struct Injected<std::unique_ptr<T>>
{
using type = T;
explicit Injected(std::unique_ptr<T> pT)
: unique(std::move(pT))
{
}
Injected(const Injected&) = default;
Injected& operator=(const Injected&) = default;
Injected(Injected&& rhs)
: unique(std::move(rhs.unique))
{
}
Injected& operator=(Injected&& rhs)
{
unique = std::move(rhs.unique);
return *this;
}
T* operator->() { return unique.get(); }
const T* operator->() const { return unique.get(); }
T& operator*() { return *unique; }
const T& operator*() const { return *unique; }
std::unique_ptr<T> unique;
};
template <typename T>
Injected<std::unique_ptr<T>> injectUnique(std::unique_ptr<T> unique)
{
return Injected<std::unique_ptr<T>>(std::move(unique));
}
} }