|
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. |
3 | 3 |
|
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. |
6 | 8 |
|
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. |
8 | 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. |
9 | 24 |
|
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 { |
17 | 36 |
|
18 | 37 | 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>; |
28 | 40 |
|
29 | 41 | 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>; |
33 | 48 |
|
| 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)"); |
34 | 55 |
|
| 56 | + [[nodiscard]] explicit constexpr moving_ref(reference_type ref_ LIFETIMEBOUND) noexcept : ref{ &ref_ } {} |
35 | 57 |
|
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"); |
41 | 59 |
|
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; |
48 | 64 | }; |
49 | 65 |
|
50 | | -} |
| 66 | +}// namespace lefticus::tools |
51 | 67 |
|
52 | 68 | #endif |
53 | | - |
|
0 commit comments