Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ cmake_minimum_required(VERSION 3.21)

# Only set the cxx_standard if it is not set by someone else
if (NOT DEFINED CMAKE_CXX_STANDARD)
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD 26)
endif()

# strongly encouraged to enable this globally to avoid conflicts between
Expand Down
63 changes: 63 additions & 0 deletions include/lefticus/tools/forwarding_ref.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
/*
This is free and unencumbered software released into the public domain.

Anyone is free to copy, modify, publish, use, compile, sell, or
distribute this software, either in source code form or as a compiled
binary, for any purpose, commercial or non-commercial, and by any
means.

In jurisdictions that recognize copyright laws, the author or authors
of this software dedicate any and all copyright interest in the
software to the public domain. We make this dedication for the benefit
of the public at large and to the detriment of our heirs and
successors. We intend this dedication to be an overt act of
relinquishment in perpetuity of all present and future rights to this
software under copyright law.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.

For more information, please refer to <https://unlicense.org>
*/


#ifndef LEFTICUS_TOOLS_FORWARDING_REF_HPP
#define LEFTICUS_TOOLS_FORWARDING_REF_HPP

#include <type_traits>

#include "lifetimebound.hpp"

namespace lefticus::tools {

template<typename T> struct [[nodiscard]] forwarding_ref

Check warning on line 38 in include/lefticus/tools/forwarding_ref.hpp

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Add message to "[[nodiscard]]" attribute explaining why return values of this type should not be discarded.

See more on https://sonarcloud.io/project/issues?id=lefticus_tools&issues=AZzK6kk9LSFP-gpY-9ZE&open=AZzK6kk9LSFP-gpY-9ZE&pullRequest=16
{
using pointer_type = std::add_pointer_t<std::remove_reference_t<T>>;
using reference_type = T;

forwarding_ref(forwarding_ref &&) = delete (
"you accidentally moved a ref (auto obj = std::move(ref)) instead of (Type obj = ref)");
forwarding_ref(const forwarding_ref &) = delete (
"you accidentally copied a ref (auto obj = ref) instead of (Type obj = ref)");
forwarding_ref &operator=(forwarding_ref &&) = delete (
"you accidentally move assigned a ref (ref = std::move(other_ref))");
forwarding_ref &operator=(const forwarding_ref &) = delete ("you accidentally copy assigned a ref (ref = other_ref)");

[[nodiscard]] explicit constexpr forwarding_ref(reference_type ref_ LIFETIMEBOUND) noexcept : ref{ &ref_ } {}
[[nodiscard]] constexpr operator reference_type() noexcept LIFETIMEBOUND { return static_cast<reference_type>(*ref); }

Check failure on line 52 in include/lefticus/tools/forwarding_ref.hpp

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Replace this conversion operator with a function or (C++11) add the "explicit" keyword.

See more on https://sonarcloud.io/project/issues?id=lefticus_tools&issues=AZzK1_G6Qh-IuXSncYXH&open=AZzK1_G6Qh-IuXSncYXH&pullRequest=16

private:
pointer_type ref;
};

template<typename T> forwarding_ref(T &&) -> forwarding_ref<T &&>;


}// namespace lefticus::tools

#endif
60 changes: 60 additions & 0 deletions include/lefticus/tools/has_move_ctor.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
/*
This is free and unencumbered software released into the public domain.

Anyone is free to copy, modify, publish, use, compile, sell, or
distribute this software, either in source code form or as a compiled
binary, for any purpose, commercial or non-commercial, and by any
means.

In jurisdictions that recognize copyright laws, the author or authors
of this software dedicate any and all copyright interest in the
software to the public domain. We make this dedication for the benefit
of the public at large and to the detriment of our heirs and
successors. We intend this dedication to be an overt act of
relinquishment in perpetuity of all present and future rights to this
software under copyright law.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.

For more information, please refer to <https://unlicense.org>
*/


#ifndef LEFTICUS_TOOLS_HAS_MOVE_CTOR_HPP
#define LEFTICUS_TOOLS_HAS_MOVE_CTOR_HPP

#include <concepts>

namespace lefticus::tools {

template<class P> struct DetectMoveConstruction
{
operator P const &();

Check failure on line 38 in include/lefticus/tools/has_move_ctor.hpp

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Replace this conversion operator with a function or (C++11) add the "explicit" keyword.

See more on https://sonarcloud.io/project/issues?id=lefticus_tools&issues=AZzK16ARDgifRzo47jJN&open=AZzK16ARDgifRzo47jJN&pullRequest=16
operator P &&();

Check failure on line 39 in include/lefticus/tools/has_move_ctor.hpp

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Replace this conversion operator with a function or (C++11) add the "explicit" keyword.

See more on https://sonarcloud.io/project/issues?id=lefticus_tools&issues=AZzK16ARDgifRzo47jJO&open=AZzK16ARDgifRzo47jJO&pullRequest=16
};

template<typename T>
concept copyable_xor_moveable = requires(T t, DetectMoveConstruction<T> m)
{
// borrowed from
// https://stackoverflow.com/questions/51901837/how-to-get-if-a-type-is-truly-move-constructible/51912859#51912859
// if this line below compiles then we know we only have either
// a move assignment or a copy assignment, otherwise
// it would be ambiguous
// we cannot detect the constructor because MSVC
// seems to have a bug, but we can detect assignment!
t = m;
};

template<typename T>
concept has_move_ctor = std::move_constructible<T> && !copyable_xor_moveable<T>;

}// namespace lefticus::tools

#endif
41 changes: 41 additions & 0 deletions include/lefticus/tools/lifetimebound.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
/*
This is free and unencumbered software released into the public domain.

Anyone is free to copy, modify, publish, use, compile, sell, or
distribute this software, either in source code form or as a compiled
binary, for any purpose, commercial or non-commercial, and by any
means.

In jurisdictions that recognize copyright laws, the author or authors
of this software dedicate any and all copyright interest in the
software to the public domain. We make this dedication for the benefit
of the public at large and to the detriment of our heirs and
successors. We intend this dedication to be an overt act of
relinquishment in perpetuity of all present and future rights to this
software under copyright law.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.

For more information, please refer to <https://unlicense.org>
*/


#ifndef LEFTICUS_TOOLS_LIFETIMEBOUND_HPP
#define LEFTICUS_TOOLS_LIFETIMEBOUND_HPP


#if defined(__has_cpp_attribute)
#if __has_cpp_attribute(clang::lifetimebound)
#define LIFETIMEBOUND [[clang::lifetimebound]]
#else
#define LIFETIMEBOUND
#endif
#endif

#endif
89 changes: 52 additions & 37 deletions include/lefticus/tools/moving_ref.hpp
Original file line number Diff line number Diff line change
@@ -1,53 +1,68 @@
#ifndef LEFTICUS_TOOLS_MOVING_REF_HPP
#define LEFTICUS_TOOLS_MOVING_REF_HPP
/*
This is free and unencumbered software released into the public domain.

#include <type_traits>
#include <utility>
Anyone is free to copy, modify, publish, use, compile, sell, or
distribute this software, either in source code form or as a compiled
binary, for any purpose, commercial or non-commercial, and by any
means.

namespace lefticus {
In jurisdictions that recognize copyright laws, the author or authors
of this software dedicate any and all copyright interest in the
software to the public domain. We make this dedication for the benefit
of the public at large and to the detriment of our heirs and
successors. We intend this dedication to be an overt act of
relinquishment in perpetuity of all present and future rights to this
software under copyright law.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.

#ifdef __cpp_concepts
template<class P>
struct DetectMoveConstruction
{
constexpr operator P const&();
constexpr operator P&&();
};
For more information, please refer to <https://unlicense.org>
*/


#ifndef LEFTICUS_TOOLS_MOVING_REF_HPP
#define LEFTICUS_TOOLS_MOVING_REF_HPP

#include "has_move_ctor.hpp"
#include "lifetimebound.hpp"

namespace lefticus::tools {

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

Check warning on line 38 in include/lefticus/tools/moving_ref.hpp

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Replace alternative operator "not" with "!".

See more on https://sonarcloud.io/project/issues?id=lefticus_tools&issues=AZzK1_ELQh-IuXSncYXD&open=AZzK1_ELQh-IuXSncYXD&pullRequest=16
T> && not std::is_pointer_v<T> && not std::is_reference_v<T>;

Check warning on line 39 in include/lefticus/tools/moving_ref.hpp

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Replace alternative operator "not" with "!".

See more on https://sonarcloud.io/project/issues?id=lefticus_tools&issues=AZzK1_ELQh-IuXSncYXB&open=AZzK1_ELQh-IuXSncYXB&pullRequest=16

Check warning on line 39 in include/lefticus/tools/moving_ref.hpp

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Replace alternative operator "not" with "!".

See more on https://sonarcloud.io/project/issues?id=lefticus_tools&issues=AZzK1_ELQh-IuXSncYXC&open=AZzK1_ELQh-IuXSncYXC&pullRequest=16

template<typename T>
concept has_move_ctor =
std::move_constructible<T> && !copyable_xor_moveable<T>;
#endif
requires movable<T> && has_move_ctor<T>
struct [[nodiscard]] moving_ref

Check warning on line 43 in include/lefticus/tools/moving_ref.hpp

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Add message to "[[nodiscard]]" attribute explaining why return values of this type should not be discarded.

See more on https://sonarcloud.io/project/issues?id=lefticus_tools&issues=AZzK6kixLSFP-gpY-9ZD&open=AZzK6kixLSFP-gpY-9ZD&pullRequest=16
{
using value_type = T;
using pointer_type = std::add_pointer_t<T>;
using reference_type = std::add_rvalue_reference_t<T>;

moving_ref(moving_ref &&) = delete (
"you accidentally moved a ref (auto obj = std::move(ref)) instead of (Type obj = ref)");
moving_ref(const moving_ref &) = delete (
"you accidentally copied a ref (auto obj = ref) instead of (Type obj = ref)");
moving_ref &operator=(moving_ref &&) = delete ("you accidentally move assigned a ref (ref = std::move(other_ref))");
moving_ref &operator=(const moving_ref &) = delete ("you accidentally copy assigned a ref (ref = other_ref)");

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

#ifdef __cpp_concepts
template<has_move_ctor T>
#else
template<typename T>
#endif
moving_ref(const T &) = delete ("this type is only to be used with rvalue reference parameters");

struct moving_ref {
constexpr moving_ref(T &&val) : ref{std::move(val)} {}
constexpr operator T&&() {
return std::move(ref);
}
T &&ref;
[[nodiscard]] constexpr operator reference_type() noexcept LIFETIMEBOUND { return static_cast<reference_type>(*ref); }

Check failure on line 60 in include/lefticus/tools/moving_ref.hpp

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Replace this conversion operator with a function or (C++11) add the "explicit" keyword.

See more on https://sonarcloud.io/project/issues?id=lefticus_tools&issues=AZzK1_ELQh-IuXSncYXF&open=AZzK1_ELQh-IuXSncYXF&pullRequest=16

private:
pointer_type ref;
};

}
}// namespace lefticus::tools

#endif

16 changes: 8 additions & 8 deletions include/lefticus/tools/non_promoting_ints.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -245,22 +245,22 @@ using int_np64_t = int_np<std::int64_t>;

namespace literals {

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

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

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

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


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

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

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

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

}// namespace lefticus::tools
Expand Down
74 changes: 74 additions & 0 deletions include/lefticus/tools/polymorphic_variant.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
#ifndef LEFTICUS_TOOLS_POLYMORPHIC_VARIANT_HPP
#define LEFTICUS_TOOLS_POLYMORPHIC_VARIANT_HPP

namespace lefticus::tools {
template<typename Base, typename... Type> const Base *get_base(const std::variant<Type...> &input)
{
const Base *retval = nullptr;

((retval = retval ? retval : std::get_if<Type>(&input)), ...);

return retval;
}

template<typename Base, typename... Type_List> Base *get_base(std::variant<Type_List...> &input)
{
Base *retval = nullptr;

((retval = retval ? retval : std::get_if<Type_List>(&input)), ...);

return retval;
}

// a variant-based type that allows polymorphic access to the underlying
// data
template<typename Base, typename... Derived>
requires std::is_polymorphic_v<Base> &&(std::is_base_of_v<Base, Derived> &&...)
&& (std::is_final_v<Derived> && ...) class polymorphic_variant
{
public:
polymorphic_variant() = delete;

using concrete_Type_List = Type_List<Derived...>;
using contained_type = decltype(variant_type(concrete_Type_List{}));

// allow any of the non-abstract supported Type_List in
template<typename Param>
constexpr explicit polymorphic_variant(
Param &&p) requires contains_type_v<std::remove_cvref_t<Param>, concrete_Type_List>
: value{ std::forward<Param>(p) }
{}

// anything that isn't an exact match for one of the supported Type_List
// is deleted. Why? We don't want to slice!
template<typename Param> constexpr explicit polymorphic_variant(Param &&) = delete;

template<typename T, typename... Args>
constexpr explicit polymorphic_variant(std::in_place_type_t<T> ipt, Args &&...args)
: value(ipt, std::forward<Args>(args)...)
{}

[[nodiscard]] constexpr Base *get() { return get_base<Base>(value); }
[[nodiscard]] constexpr const Base *get() const { return get_base<Base>(value); }

[[nodiscard]] constexpr Base &operator*() { return *get(); }
[[nodiscard]] constexpr const Base &operator*() const { return *get(); }

[[nodiscard]] constexpr Base *operator->() { return get(); }
[[nodiscard]] constexpr const Base *operator->() const { return get(); }

private:
[[nodiscard]] constexpr static auto getter() noexcept
{
return [](auto &obj) -> Base * { return &obj; };
}

[[nodiscard]] constexpr static auto const_getter() noexcept
{
return [](const auto &obj) -> const Base * { return &obj; };
}

contained_type value;
};
}// namespace lefticus::tools
#endif
Loading
Loading