-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathpolymorphic_value.h
More file actions
46 lines (34 loc) · 1.34 KB
/
polymorphic_value.h
File metadata and controls
46 lines (34 loc) · 1.34 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
#pragma once
#include <functional>
#include <type_traits>
namespace nonstd {
template <typename IFace> class polymorphic_value { // NOLINT
public:
using value_type = IFace;
polymorphic_value() = default;
template <typename Concrete, typename = std::enable_if_t<std::is_copy_constructible_v<Concrete>>>
explicit polymorphic_value(Concrete conc)
: obj_([obj = std::move(conc)]() mutable -> IFace * { return &obj; }) {
static_assert(std::is_base_of_v<IFace, Concrete>);
}
~polymorphic_value() = default;
polymorphic_value(const polymorphic_value &o) : obj_(o.obj_) {}
polymorphic_value(polymorphic_value &&o) noexcept : obj_(std::move(o.obj_)) {}
auto operator=(polymorphic_value o) -> polymorphic_value & {
o.swap(*this);
return *this;
}
constexpr auto operator*() const noexcept -> const IFace & { return *ptr_; }
constexpr auto operator*() noexcept -> IFace & { return *ptr_; }
constexpr auto operator->() const noexcept -> const IFace * { return ptr_; }
constexpr auto operator->() noexcept -> IFace * { return ptr_; }
friend inline void swap(polymorphic_value &a, polymorphic_value &b) noexcept { a.swap(b); }
private:
void swap(polymorphic_value &o) noexcept {
std::swap(obj_, o.obj_);
std::swap(ptr_, o.ptr_);
}
std::function<IFace *()> obj_;
IFace *ptr_ = obj_();
};
} // namespace nonstd