/* Copyright 2016, Ableton AG, Berlin. All rights reserved. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * If you would like to incorporate Link into a proprietary software application, * please contact . */ #pragma once #include namespace ableton { namespace util { // Utility type for aiding in dependency injection. // Base template and implementation for injected valued template 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; }; // Utility function for injecting values template Injected injectVal(T t) { return Injected(std::move(t)); } // Specialization for injected references template struct Injected { 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 ref; }; // Utility function for injecting references template Injected injectRef(T& t) { return Injected(t); } // Specialization for injected shared_ptr template struct Injected> { using type = T; explicit Injected(std::shared_ptr 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 shared; }; // Utility function for injected shared_ptr template Injected> injectShared(std::shared_ptr shared) { return Injected>(std::move(shared)); } // Specialization for injected unique_ptr template struct Injected> { using type = T; explicit Injected(std::unique_ptr 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 unique; }; // Utility function for injected unique_ptr template Injected> injectUnique(std::unique_ptr unique) { return Injected>(std::move(unique)); } } // namespace util } // namespace ableton