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
15namespace 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
39template <typename Derived, typename Base>
40class Cloneable : public Base {
41public:
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