Skip to content

Commit 4afe430

Browse files
committed
Merge branch 'forwarding_ref'
2 parents 0c4e79f + 6a6fdf7 commit 4afe430

13 files changed

Lines changed: 516 additions & 223 deletions

CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ cmake_minimum_required(VERSION 3.21)
66

77
# Only set the cxx_standard if it is not set by someone else
88
if (NOT DEFINED CMAKE_CXX_STANDARD)
9-
set(CMAKE_CXX_STANDARD 20)
9+
set(CMAKE_CXX_STANDARD 26)
1010
endif()
1111

1212
# strongly encouraged to enable this globally to avoid conflicts between
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
/*
2+
This is free and unencumbered software released into the public domain.
3+
4+
Anyone is free to copy, modify, publish, use, compile, sell, or
5+
distribute this software, either in source code form or as a compiled
6+
binary, for any purpose, commercial or non-commercial, and by any
7+
means.
8+
9+
In jurisdictions that recognize copyright laws, the author or authors
10+
of this software dedicate any and all copyright interest in the
11+
software to the public domain. We make this dedication for the benefit
12+
of the public at large and to the detriment of our heirs and
13+
successors. We intend this dedication to be an overt act of
14+
relinquishment in perpetuity of all present and future rights to this
15+
software under copyright law.
16+
17+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
20+
IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
21+
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
22+
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
23+
OTHER DEALINGS IN THE SOFTWARE.
24+
25+
For more information, please refer to <https://unlicense.org>
26+
*/
27+
28+
29+
#ifndef LEFTICUS_TOOLS_FORWARDING_REF_HPP
30+
#define LEFTICUS_TOOLS_FORWARDING_REF_HPP
31+
32+
#include <type_traits>
33+
34+
#include "lifetimebound.hpp"
35+
36+
namespace lefticus::tools {
37+
38+
template<typename T> struct [[nodiscard]] forwarding_ref
39+
{
40+
using pointer_type = std::add_pointer_t<std::remove_reference_t<T>>;
41+
using reference_type = T;
42+
43+
forwarding_ref(forwarding_ref &&) = delete (
44+
"you accidentally moved a ref (auto obj = std::move(ref)) instead of (Type obj = ref)");
45+
forwarding_ref(const forwarding_ref &) = delete (
46+
"you accidentally copied a ref (auto obj = ref) instead of (Type obj = ref)");
47+
forwarding_ref &operator=(forwarding_ref &&) = delete (
48+
"you accidentally move assigned a ref (ref = std::move(other_ref))");
49+
forwarding_ref &operator=(const forwarding_ref &) = delete ("you accidentally copy assigned a ref (ref = other_ref)");
50+
51+
[[nodiscard]] explicit constexpr forwarding_ref(reference_type ref_ LIFETIMEBOUND) noexcept : ref{ &ref_ } {}
52+
[[nodiscard]] constexpr operator reference_type() noexcept LIFETIMEBOUND { return static_cast<reference_type>(*ref); }
53+
54+
private:
55+
pointer_type ref;
56+
};
57+
58+
template<typename T> forwarding_ref(T &&) -> forwarding_ref<T &&>;
59+
60+
61+
}// namespace lefticus::tools
62+
63+
#endif
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
/*
2+
This is free and unencumbered software released into the public domain.
3+
4+
Anyone is free to copy, modify, publish, use, compile, sell, or
5+
distribute this software, either in source code form or as a compiled
6+
binary, for any purpose, commercial or non-commercial, and by any
7+
means.
8+
9+
In jurisdictions that recognize copyright laws, the author or authors
10+
of this software dedicate any and all copyright interest in the
11+
software to the public domain. We make this dedication for the benefit
12+
of the public at large and to the detriment of our heirs and
13+
successors. We intend this dedication to be an overt act of
14+
relinquishment in perpetuity of all present and future rights to this
15+
software under copyright law.
16+
17+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
20+
IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
21+
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
22+
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
23+
OTHER DEALINGS IN THE SOFTWARE.
24+
25+
For more information, please refer to <https://unlicense.org>
26+
*/
27+
28+
29+
#ifndef LEFTICUS_TOOLS_HAS_MOVE_CTOR_HPP
30+
#define LEFTICUS_TOOLS_HAS_MOVE_CTOR_HPP
31+
32+
#include <concepts>
33+
34+
namespace lefticus::tools {
35+
36+
template<class P> struct DetectMoveConstruction
37+
{
38+
operator P const &();
39+
operator P &&();
40+
};
41+
42+
template<typename T>
43+
concept copyable_xor_moveable = requires(T t, DetectMoveConstruction<T> m)
44+
{
45+
// borrowed from
46+
// https://stackoverflow.com/questions/51901837/how-to-get-if-a-type-is-truly-move-constructible/51912859#51912859
47+
// if this line below compiles then we know we only have either
48+
// a move assignment or a copy assignment, otherwise
49+
// it would be ambiguous
50+
// we cannot detect the constructor because MSVC
51+
// seems to have a bug, but we can detect assignment!
52+
t = m;
53+
};
54+
55+
template<typename T>
56+
concept has_move_ctor = std::move_constructible<T> && !copyable_xor_moveable<T>;
57+
58+
}// namespace lefticus::tools
59+
60+
#endif
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
/*
2+
This is free and unencumbered software released into the public domain.
3+
4+
Anyone is free to copy, modify, publish, use, compile, sell, or
5+
distribute this software, either in source code form or as a compiled
6+
binary, for any purpose, commercial or non-commercial, and by any
7+
means.
8+
9+
In jurisdictions that recognize copyright laws, the author or authors
10+
of this software dedicate any and all copyright interest in the
11+
software to the public domain. We make this dedication for the benefit
12+
of the public at large and to the detriment of our heirs and
13+
successors. We intend this dedication to be an overt act of
14+
relinquishment in perpetuity of all present and future rights to this
15+
software under copyright law.
16+
17+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
20+
IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
21+
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
22+
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
23+
OTHER DEALINGS IN THE SOFTWARE.
24+
25+
For more information, please refer to <https://unlicense.org>
26+
*/
27+
28+
29+
#ifndef LEFTICUS_TOOLS_LIFETIMEBOUND_HPP
30+
#define LEFTICUS_TOOLS_LIFETIMEBOUND_HPP
31+
32+
33+
#if defined(__has_cpp_attribute)
34+
#if __has_cpp_attribute(clang::lifetimebound)
35+
#define LIFETIMEBOUND [[clang::lifetimebound]]
36+
#else
37+
#define LIFETIMEBOUND
38+
#endif
39+
#endif
40+
41+
#endif

include/lefticus/tools/moving_ref.hpp

Lines changed: 52 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1,53 +1,68 @@
1-
#ifndef LEFTICUS_TOOLS_MOVING_REF_HPP
2-
#define LEFTICUS_TOOLS_MOVING_REF_HPP
1+
/*
2+
This is free and unencumbered software released into the public domain.
33
4-
#include <type_traits>
5-
#include <utility>
4+
Anyone is free to copy, modify, publish, use, compile, sell, or
5+
distribute this software, either in source code form or as a compiled
6+
binary, for any purpose, commercial or non-commercial, and by any
7+
means.
68
7-
namespace lefticus {
9+
In jurisdictions that recognize copyright laws, the author or authors
10+
of this software dedicate any and all copyright interest in the
11+
software to the public domain. We make this dedication for the benefit
12+
of the public at large and to the detriment of our heirs and
13+
successors. We intend this dedication to be an overt act of
14+
relinquishment in perpetuity of all present and future rights to this
15+
software under copyright law.
816
17+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
20+
IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
21+
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
22+
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
23+
OTHER DEALINGS IN THE SOFTWARE.
924
10-
#ifdef __cpp_concepts
11-
template<class P>
12-
struct DetectMoveConstruction
13-
{
14-
constexpr operator P const&();
15-
constexpr operator P&&();
16-
};
25+
For more information, please refer to <https://unlicense.org>
26+
*/
27+
28+
29+
#ifndef LEFTICUS_TOOLS_MOVING_REF_HPP
30+
#define LEFTICUS_TOOLS_MOVING_REF_HPP
31+
32+
#include "has_move_ctor.hpp"
33+
#include "lifetimebound.hpp"
34+
35+
namespace lefticus::tools {
1736

1837
template<typename T>
19-
concept copyable_xor_moveable = requires (T t, DetectMoveConstruction<T> m) {
20-
// borrowed from https://stackoverflow.com/questions/51901837/how-to-get-if-a-type-is-truly-move-constructible/51912859#51912859
21-
// if this line below compiles then we know we only have either
22-
// a move assignment or a copy assignment, otherwise
23-
// it would be ambiguous
24-
// we cannot detect the constructor because MSVC
25-
// seems to have a bug, but we can detect assignment!
26-
t = m;
27-
};
38+
concept movable = std::is_move_constructible_v<T> && std::is_move_assignable_v<T> && not std::is_const_v<
39+
T> && not std::is_pointer_v<T> && not std::is_reference_v<T>;
2840

2941
template<typename T>
30-
concept has_move_ctor =
31-
std::move_constructible<T> && !copyable_xor_moveable<T>;
32-
#endif
42+
requires movable<T> && has_move_ctor<T>
43+
struct [[nodiscard]] moving_ref
44+
{
45+
using value_type = T;
46+
using pointer_type = std::add_pointer_t<T>;
47+
using reference_type = std::add_rvalue_reference_t<T>;
3348

49+
moving_ref(moving_ref &&) = delete (
50+
"you accidentally moved a ref (auto obj = std::move(ref)) instead of (Type obj = ref)");
51+
moving_ref(const moving_ref &) = delete (
52+
"you accidentally copied a ref (auto obj = ref) instead of (Type obj = ref)");
53+
moving_ref &operator=(moving_ref &&) = delete ("you accidentally move assigned a ref (ref = std::move(other_ref))");
54+
moving_ref &operator=(const moving_ref &) = delete ("you accidentally copy assigned a ref (ref = other_ref)");
3455

56+
[[nodiscard]] explicit constexpr moving_ref(reference_type ref_ LIFETIMEBOUND) noexcept : ref{ &ref_ } {}
3557

36-
#ifdef __cpp_concepts
37-
template<has_move_ctor T>
38-
#else
39-
template<typename T>
40-
#endif
58+
moving_ref(const T &) = delete ("this type is only to be used with rvalue reference parameters");
4159

42-
struct moving_ref {
43-
constexpr moving_ref(T &&val) : ref{std::move(val)} {}
44-
constexpr operator T&&() {
45-
return std::move(ref);
46-
}
47-
T &&ref;
60+
[[nodiscard]] constexpr operator reference_type() noexcept LIFETIMEBOUND { return static_cast<reference_type>(*ref); }
61+
62+
private:
63+
pointer_type ref;
4864
};
4965

50-
}
66+
}// namespace lefticus::tools
5167

5268
#endif
53-

include/lefticus/tools/non_promoting_ints.hpp

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -245,22 +245,22 @@ using int_np64_t = int_np<std::int64_t>;
245245

246246
namespace literals {
247247

248-
consteval auto operator"" _npu8(unsigned long long val) { return uint_np8_t::from(val); }
248+
consteval auto operator""_npu8(unsigned long long val) { return uint_np8_t::from(val); }
249249

250-
consteval auto operator"" _npu16(unsigned long long val) { return uint_np16_t::from(val); }
250+
consteval auto operator""_npu16(unsigned long long val) { return uint_np16_t::from(val); }
251251

252-
consteval auto operator"" _npu32(unsigned long long val) { return uint_np32_t::from(val); }
252+
consteval auto operator""_npu32(unsigned long long val) { return uint_np32_t::from(val); }
253253

254-
consteval auto operator"" _npu64(unsigned long long val) { return uint_np64_t::from(val); }
254+
consteval auto operator""_npu64(unsigned long long val) { return uint_np64_t::from(val); }
255255

256256

257-
consteval auto operator"" _np8(unsigned long long val) { return int_np8_t::from(val); }
257+
consteval auto operator""_np8(unsigned long long val) { return int_np8_t::from(val); }
258258

259-
consteval auto operator"" _np16(unsigned long long val) { return int_np16_t::from(val); }
259+
consteval auto operator""_np16(unsigned long long val) { return int_np16_t::from(val); }
260260

261-
consteval auto operator"" _np32(unsigned long long val) { return int_np32_t::from(val); }
261+
consteval auto operator""_np32(unsigned long long val) { return int_np32_t::from(val); }
262262

263-
consteval auto operator"" _np64(unsigned long long val) { return int_np64_t::from(val); }
263+
consteval auto operator""_np64(unsigned long long val) { return int_np64_t::from(val); }
264264
}// namespace literals
265265

266266
}// namespace lefticus::tools
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
#ifndef LEFTICUS_TOOLS_POLYMORPHIC_VARIANT_HPP
2+
#define LEFTICUS_TOOLS_POLYMORPHIC_VARIANT_HPP
3+
4+
namespace lefticus::tools {
5+
template<typename Base, typename... Type> const Base *get_base(const std::variant<Type...> &input)
6+
{
7+
const Base *retval = nullptr;
8+
9+
((retval = retval ? retval : std::get_if<Type>(&input)), ...);
10+
11+
return retval;
12+
}
13+
14+
template<typename Base, typename... Type_List> Base *get_base(std::variant<Type_List...> &input)
15+
{
16+
Base *retval = nullptr;
17+
18+
((retval = retval ? retval : std::get_if<Type_List>(&input)), ...);
19+
20+
return retval;
21+
}
22+
23+
// a variant-based type that allows polymorphic access to the underlying
24+
// data
25+
template<typename Base, typename... Derived>
26+
requires std::is_polymorphic_v<Base> &&(std::is_base_of_v<Base, Derived> &&...)
27+
&& (std::is_final_v<Derived> && ...) class polymorphic_variant
28+
{
29+
public:
30+
polymorphic_variant() = delete;
31+
32+
using concrete_Type_List = Type_List<Derived...>;
33+
using contained_type = decltype(variant_type(concrete_Type_List{}));
34+
35+
// allow any of the non-abstract supported Type_List in
36+
template<typename Param>
37+
constexpr explicit polymorphic_variant(
38+
Param &&p) requires contains_type_v<std::remove_cvref_t<Param>, concrete_Type_List>
39+
: value{ std::forward<Param>(p) }
40+
{}
41+
42+
// anything that isn't an exact match for one of the supported Type_List
43+
// is deleted. Why? We don't want to slice!
44+
template<typename Param> constexpr explicit polymorphic_variant(Param &&) = delete;
45+
46+
template<typename T, typename... Args>
47+
constexpr explicit polymorphic_variant(std::in_place_type_t<T> ipt, Args &&...args)
48+
: value(ipt, std::forward<Args>(args)...)
49+
{}
50+
51+
[[nodiscard]] constexpr Base *get() { return get_base<Base>(value); }
52+
[[nodiscard]] constexpr const Base *get() const { return get_base<Base>(value); }
53+
54+
[[nodiscard]] constexpr Base &operator*() { return *get(); }
55+
[[nodiscard]] constexpr const Base &operator*() const { return *get(); }
56+
57+
[[nodiscard]] constexpr Base *operator->() { return get(); }
58+
[[nodiscard]] constexpr const Base *operator->() const { return get(); }
59+
60+
private:
61+
[[nodiscard]] constexpr static auto getter() noexcept
62+
{
63+
return [](auto &obj) -> Base * { return &obj; };
64+
}
65+
66+
[[nodiscard]] constexpr static auto const_getter() noexcept
67+
{
68+
return [](const auto &obj) -> const Base * { return &obj; };
69+
}
70+
71+
contained_type value;
72+
};
73+
}// namespace lefticus::tools
74+
#endif

0 commit comments

Comments
 (0)