1 //===-- Cloneable.h ---------------------------------------------*- C++ -*-===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #ifndef LLDB_UTILITY_CLONEABLE_H 10 #define LLDB_UTILITY_CLONEABLE_H 11 12 #include <memory> 13 #include <type_traits> 14 15 namespace lldb_private { 16 17 /// \class Cloneable Cloneable.h "lldb/Utility/Cloneable.h" 18 /// A class that implements CRTP-based "virtual constructor" idiom. 19 /// 20 /// Example: 21 /// @code 22 /// class Base { 23 /// using TopmostBase = Base; 24 /// public: 25 /// virtual std::shared_ptr<Base> Clone() const = 0; 26 /// }; 27 /// @endcode 28 /// 29 /// To define a class derived from the Base with overridden Clone: 30 /// @code 31 /// class Intermediate : public Cloneable<Intermediate, Base> {}; 32 /// @endcode 33 /// 34 /// To define a class at the next level of inheritance with overridden Clone: 35 /// @code 36 /// class Derived : public Cloneable<Derived, Intermediate> {}; 37 /// @endcode 38 39 template <typename Derived, typename Base> 40 class Cloneable : public Base { 41 public: 42 using Base::Base; 43 Clone()44 std::shared_ptr<typename Base::TopmostBase> Clone() const override { 45 // std::is_base_of requires derived type to be complete, that's why class 46 // scope static_assert cannot be used. 47 static_assert(std::is_base_of<Cloneable, Derived>::value, 48 "Derived class must be derived from this."); 49 50 return std::make_shared<Derived>(static_cast<const Derived &>(*this)); 51 } 52 }; 53 54 } // namespace lldb_private 55 56 #endif // LLDB_UTILITY_CLONEABLE_H 57