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 
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