Skip to content

Commit 508deb7

Browse files
committed
update docs
1 parent a876ab7 commit 508deb7

File tree

7 files changed

+286
-130
lines changed

7 files changed

+286
-130
lines changed

.github/workflows/sanitizers.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ jobs:
1616
{ cxx: clang++-16, pkgs: clang-16 },
1717
{ cxx: clang++-17, pkgs: clang-17 },
1818
{ cxx: clang++-18, pkgs: clang-18 },
19+
{ cxx: clang++-19, pkgs: clang-19 },
1920
{ cxx: g++-11, pkgs: g++-11 },
2021
{ cxx: g++-12, pkgs: g++-12 },
2122
{ cxx: g++-13, pkgs: g++-13 },

CMakeLists.txt

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ include(GNUInstallDirs)
66
include(CMakePackageConfigHelpers)
77

88
option(SMP_BUILD_BENCHMARKS "Build the benchmarks for the library when ON." ON)
9+
option(SMP_BUILD_EXAMPLES "Build the examples for the library when ON." ON)
910

1011
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/build")
1112
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
@@ -54,6 +55,10 @@ if(BUILD_TESTING)
5455
add_subdirectory("${CMAKE_CURRENT_SOURCE_DIR}/test")
5556
endif()
5657

57-
if (SMP_BUILD_BENCHMARKS)
58+
if(SMP_BUILD_BENCHMARKS)
5859
add_subdirectory("${CMAKE_CURRENT_SOURCE_DIR}/benchmark")
5960
endif()
61+
62+
if(SMP_BUILD_EXAMPLES)
63+
add_subdirectory("${CMAKE_CURRENT_SOURCE_DIR}/example")
64+
endif()

README.md

Lines changed: 186 additions & 128 deletions
Large diffs are not rendered by default.

example/CMakeLists.txt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
#find_package(benchmark REQUIRED)
2+
3+
add_executable(small_unique_ptr_example "${CMAKE_CURRENT_SOURCE_DIR}/move_only_function.cpp")
4+
target_link_libraries(small_unique_ptr_example PRIVATE small_unique_ptr)

example/move_only_function.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
#include "move_only_function.hpp"
2+
#include <iostream>
3+
4+
int main() {
5+
move_only_function<void()> f = [] { std::cout << "Hi\n"; };
6+
f();
7+
}

example/move_only_function.hpp

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
#ifndef MOVE_ONLY_FUNCTION_HPP
2+
#define MOVE_ONLY_FUNCTION_HPP
3+
4+
#include <functional>
5+
#include <memory>
6+
#include <type_traits>
7+
#include <utility>
8+
#include <cstddef>
9+
#include "small_unique_ptr.hpp"
10+
11+
template<typename...>
12+
class move_only_function;
13+
14+
template<typename Ret, typename... Args>
15+
class move_only_function<Ret(Args...)>
16+
{
17+
public:
18+
constexpr move_only_function() noexcept = default;
19+
constexpr move_only_function(std::nullptr_t) noexcept {}
20+
21+
template<typename F>
22+
requires(!std::is_same_v<std::remove_reference_t<F>, move_only_function> && std::is_invocable_r_v<Ret, F&, Args...>)
23+
constexpr move_only_function(F&& f) :
24+
fptr_(smp::make_unique_small<Impl<std::decay_t<F>>>(std::forward<F>(f)))
25+
{}
26+
27+
template<typename F>
28+
requires(!std::is_same_v<std::remove_reference_t<F>, move_only_function> && std::is_invocable_r_v<Ret, F&, Args...>)
29+
constexpr move_only_function& operator=(F&& f)
30+
{
31+
fptr_ = smp::make_unique_small<Impl<std::decay_t<F>>>(std::forward<F>(f));
32+
return *this;
33+
}
34+
35+
constexpr move_only_function(move_only_function&&) = default;
36+
constexpr move_only_function& operator=(move_only_function&&) = default;
37+
38+
constexpr Ret operator()(Args... args) const
39+
{
40+
return fptr_->invoke(std::forward<Args>(args)...);
41+
}
42+
43+
constexpr void swap(move_only_function& other) noexcept
44+
{
45+
fptr_.swap(other.fptr_);
46+
}
47+
48+
constexpr explicit operator bool() const noexcept { return static_cast<bool>(fptr_); }
49+
50+
private:
51+
struct ImplBase
52+
{
53+
constexpr virtual Ret invoke(Args...) = 0;
54+
constexpr virtual void small_unique_ptr_move(void* dst) noexcept = 0;
55+
constexpr virtual ~ImplBase() = default;
56+
};
57+
58+
template<typename Callable>
59+
struct Impl : public ImplBase
60+
{
61+
constexpr Impl(Callable func) noexcept(std::is_nothrow_move_constructible_v<Callable>) :
62+
func_(std::move(func))
63+
{}
64+
65+
constexpr void small_unique_ptr_move(void* dst) noexcept override
66+
{
67+
std::construct_at(static_cast<Impl*>(dst), std::move(*this));
68+
}
69+
70+
constexpr Ret invoke(Args... args) override
71+
{
72+
return std::invoke(func_, std::forward<Args>(args)...);
73+
}
74+
75+
Callable func_;
76+
};
77+
78+
smp::small_unique_ptr<ImplBase> fptr_ = nullptr;
79+
};
80+
81+
#endif // !MOVE_ONLY_FUNCTION_HPP

src/small_unique_ptr.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ namespace smp::detail
4242
}
4343

4444
template<typename T>
45-
concept has_virtual_move = requires(std::remove_cv_t<T> object, void* const dst)
45+
concept has_virtual_move = requires(std::remove_cv_t<T>& object, void* const dst)
4646
{
4747
requires std::is_polymorphic_v<T>;
4848
{ object.small_unique_ptr_move(dst) } noexcept -> std::same_as<void>;

0 commit comments

Comments
 (0)