mirror of
https://github.com/BlackMATov/meta.hpp.git
synced 2025-12-15 11:52:08 +07:00
value index operator
This commit is contained in:
2
TODO.md
2
TODO.md
@@ -5,6 +5,8 @@
|
|||||||
- add meta exception class;
|
- add meta exception class;
|
||||||
- add conversion of nullptr to any pointers;
|
- add conversion of nullptr to any pointers;
|
||||||
- add conversion of any pointers to void pointer ( identically cv-qualified );
|
- add conversion of any pointers to void pointer ( identically cv-qualified );
|
||||||
|
- void value?
|
||||||
|
- all string to hash?
|
||||||
|
|
||||||
* argument names
|
* argument names
|
||||||
* argument defaults
|
* argument defaults
|
||||||
|
|||||||
@@ -182,3 +182,50 @@ namespace meta_hpp
|
|||||||
using scope_map = std::map<scope_index, scope, std::less<>>;
|
using scope_map = std::map<scope_index, scope, std::less<>>;
|
||||||
using variable_map = std::map<variable_index, variable, std::less<>>;
|
using variable_map = std::map<variable_index, variable, std::less<>>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace meta_hpp::detail::stdex
|
||||||
|
{
|
||||||
|
template < typename T >
|
||||||
|
[[nodiscard]] constexpr std::underlying_type_t<T> to_underlying(T v) noexcept {
|
||||||
|
return static_cast<std::underlying_type_t<T>>(v);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace meta_hpp::detail::stdex
|
||||||
|
{
|
||||||
|
template < typename T, typename U >
|
||||||
|
concept same_as =
|
||||||
|
std::is_same_v<T, U> &&
|
||||||
|
std::is_same_v<U, T>;
|
||||||
|
|
||||||
|
template < typename Derived, typename Base >
|
||||||
|
concept derived_from =
|
||||||
|
std::is_base_of_v<Base, Derived> &&
|
||||||
|
std::is_convertible_v<const volatile Derived*, const volatile Base*>;
|
||||||
|
|
||||||
|
template < typename From, typename To >
|
||||||
|
concept convertible_to =
|
||||||
|
std::is_convertible_v<From, To> &&
|
||||||
|
requires { static_cast<To>(std::declval<From>()); };
|
||||||
|
|
||||||
|
template < typename T >
|
||||||
|
concept destructible =
|
||||||
|
std::is_nothrow_destructible_v<T>;
|
||||||
|
|
||||||
|
template < typename T, typename... Args >
|
||||||
|
concept constructible_from =
|
||||||
|
destructible<T> &&
|
||||||
|
std::is_constructible_v<T, Args...>;
|
||||||
|
|
||||||
|
template < typename T >
|
||||||
|
concept move_constructible =
|
||||||
|
constructible_from<T, T> &&
|
||||||
|
convertible_to<T, T>;
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
concept copy_constructible =
|
||||||
|
move_constructible<T> &&
|
||||||
|
constructible_from<T, T&> && convertible_to<T&, T> &&
|
||||||
|
constructible_from<T, const T&> && convertible_to<const T&, T> &&
|
||||||
|
constructible_from<T, const T> && convertible_to<const T, T>;
|
||||||
|
}
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ namespace meta_hpp
|
|||||||
template < detail::class_kind Class >
|
template < detail::class_kind Class >
|
||||||
template < typename... Args >
|
template < typename... Args >
|
||||||
class_bind<Class>& class_bind<Class>::ctor_() {
|
class_bind<Class>& class_bind<Class>::ctor_() {
|
||||||
static_assert(detail::constructible_from<Class, Args...>);
|
static_assert(detail::stdex::constructible_from<Class, Args...>);
|
||||||
auto ctor_state = detail::ctor_state::make<Class, Args...>();
|
auto ctor_state = detail::ctor_state::make<Class, Args...>();
|
||||||
data_->ctors.emplace(ctor_state->index, std::move(ctor_state));
|
data_->ctors.emplace(ctor_state->index, std::move(ctor_state));
|
||||||
return *this;
|
return *this;
|
||||||
@@ -32,7 +32,7 @@ namespace meta_hpp
|
|||||||
template < detail::class_kind Class >
|
template < detail::class_kind Class >
|
||||||
template < detail::class_kind Base >
|
template < detail::class_kind Base >
|
||||||
class_bind<Class>& class_bind<Class>::base_() {
|
class_bind<Class>& class_bind<Class>::base_() {
|
||||||
static_assert(detail::derived_from<Class, Base>);
|
static_assert(detail::stdex::derived_from<Class, Base>);
|
||||||
data_->bases.emplace(resolve_type<Base>());
|
data_->bases.emplace(resolve_type<Base>());
|
||||||
data_->bases_info.emplace(resolve_type<Base>(), detail::class_type_data::base_info{
|
data_->bases_info.emplace(resolve_type<Base>(), detail::class_type_data::base_info{
|
||||||
.upcast = +[](void* derived) -> void* {
|
.upcast = +[](void* derived) -> void* {
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ namespace meta_hpp::detail
|
|||||||
evalue_state::evalue_state(evalue_index index, Enum value)
|
evalue_state::evalue_state(evalue_index index, Enum value)
|
||||||
: index{std::move(index)}
|
: index{std::move(index)}
|
||||||
, enum_value{value}
|
, enum_value{value}
|
||||||
, underlying_value{to_underlying(value)} {}
|
, underlying_value{stdex::to_underlying(value)} {}
|
||||||
|
|
||||||
template < enum_kind Enum >
|
template < enum_kind Enum >
|
||||||
evalue_state_ptr evalue_state::make(std::string name, Enum value) {
|
evalue_state_ptr evalue_state::make(std::string name, Enum value) {
|
||||||
|
|||||||
@@ -34,36 +34,6 @@ namespace meta_hpp::detail
|
|||||||
using copy_cvref_t = typename cvref_traits<From>::template copy_to<To>;
|
using copy_cvref_t = typename cvref_traits<From>::template copy_to<To>;
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace meta_hpp::detail
|
|
||||||
{
|
|
||||||
template < typename T >
|
|
||||||
concept destructible =
|
|
||||||
std::is_nothrow_destructible_v<T>;
|
|
||||||
|
|
||||||
template < typename T, typename... Args >
|
|
||||||
concept constructible_from =
|
|
||||||
destructible<T> &&
|
|
||||||
std::is_constructible_v<T, Args...>;
|
|
||||||
|
|
||||||
template < typename Derived, typename Base >
|
|
||||||
concept derived_from =
|
|
||||||
std::is_base_of_v<Base, Derived> &&
|
|
||||||
std::is_convertible_v<const volatile Derived*, const volatile Base*>;
|
|
||||||
|
|
||||||
template < typename From, typename To >
|
|
||||||
concept convertible_to =
|
|
||||||
std::is_convertible_v<From, To> &&
|
|
||||||
requires { static_cast<To>(std::declval<From>()); };
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace meta_hpp::detail
|
|
||||||
{
|
|
||||||
template < typename T >
|
|
||||||
[[nodiscard]] constexpr std::underlying_type_t<T> to_underlying(T v) noexcept {
|
|
||||||
return static_cast<std::underlying_type_t<T>>(v);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace meta_hpp::detail
|
namespace meta_hpp::detail
|
||||||
{
|
{
|
||||||
template < typename T >
|
template < typename T >
|
||||||
@@ -114,34 +84,6 @@ namespace meta_hpp::detail
|
|||||||
(std::is_rvalue_reference_v<T> && std::is_class_v<std::remove_reference_t<T>>);
|
(std::is_rvalue_reference_v<T> && std::is_class_v<std::remove_reference_t<T>>);
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace meta_hpp::detail
|
|
||||||
{
|
|
||||||
template < typename T >
|
|
||||||
concept has_deref_op_kind = requires(const T& v) {
|
|
||||||
{ *v } -> convertible_to<std::remove_pointer_t<T>>;
|
|
||||||
};
|
|
||||||
|
|
||||||
template < typename T >
|
|
||||||
concept has_less_op_kind = requires(const T& v) {
|
|
||||||
{ v < v } -> convertible_to<bool>;
|
|
||||||
};
|
|
||||||
|
|
||||||
template < typename T >
|
|
||||||
concept has_equals_op_kind = requires(const T& v) {
|
|
||||||
{ v == v } -> convertible_to<bool>;
|
|
||||||
};
|
|
||||||
|
|
||||||
template < typename T >
|
|
||||||
concept has_istream_op_kind = requires(std::istream& is, T& v) {
|
|
||||||
{ is >> v } -> convertible_to<std::istream&>;
|
|
||||||
};
|
|
||||||
|
|
||||||
template < typename T >
|
|
||||||
concept has_ostream_op_kind = requires(std::ostream& os, const T& v) {
|
|
||||||
{ os << v } -> convertible_to<std::ostream&>;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace meta_hpp::detail
|
namespace meta_hpp::detail
|
||||||
{
|
{
|
||||||
class noncopyable {
|
class noncopyable {
|
||||||
@@ -187,9 +129,8 @@ namespace meta_hpp
|
|||||||
[[nodiscard]] const void* data() const noexcept;
|
[[nodiscard]] const void* data() const noexcept;
|
||||||
[[nodiscard]] const void* cdata() const noexcept;
|
[[nodiscard]] const void* cdata() const noexcept;
|
||||||
|
|
||||||
[[nodiscard]] value deref();
|
[[nodiscard]] value operator*() const;
|
||||||
[[nodiscard]] value deref() const;
|
[[nodiscard]] value operator[](std::size_t index) const;
|
||||||
[[nodiscard]] value cderef() const;
|
|
||||||
|
|
||||||
template < typename T, typename Tp = std::decay_t<T> >
|
template < typename T, typename Tp = std::decay_t<T> >
|
||||||
[[nodiscard]] Tp& cast() &;
|
[[nodiscard]] Tp& cast() &;
|
||||||
|
|||||||
@@ -9,6 +9,13 @@
|
|||||||
#include "../meta_base.hpp"
|
#include "../meta_base.hpp"
|
||||||
#include "../meta_utilities.hpp"
|
#include "../meta_utilities.hpp"
|
||||||
|
|
||||||
|
#include "value_traits/deref_traits.hpp"
|
||||||
|
#include "value_traits/equals_traits.hpp"
|
||||||
|
#include "value_traits/index_traits.hpp"
|
||||||
|
#include "value_traits/istream_traits.hpp"
|
||||||
|
#include "value_traits/less_traits.hpp"
|
||||||
|
#include "value_traits/ostream_traits.hpp"
|
||||||
|
|
||||||
namespace meta_hpp
|
namespace meta_hpp
|
||||||
{
|
{
|
||||||
struct value::traits final {
|
struct value::traits final {
|
||||||
@@ -17,8 +24,8 @@ namespace meta_hpp
|
|||||||
void* (*const data)(value&) noexcept;
|
void* (*const data)(value&) noexcept;
|
||||||
const void* (*const cdata)(const value&) noexcept;
|
const void* (*const cdata)(const value&) noexcept;
|
||||||
|
|
||||||
value (*const deref)(value&);
|
value (*const deref)(const value&);
|
||||||
value (*const cderef)(const value&);
|
value (*const index)(const value&, std::size_t);
|
||||||
|
|
||||||
bool (*const less)(const value&, const value&);
|
bool (*const less)(const value&, const value&);
|
||||||
bool (*const equals)(const value&, const value&);
|
bool (*const equals)(const value&, const value&);
|
||||||
@@ -48,35 +55,35 @@ namespace meta_hpp
|
|||||||
return v.try_cast<T>();
|
return v.try_cast<T>();
|
||||||
},
|
},
|
||||||
|
|
||||||
.deref = +[]([[maybe_unused]] value& v) -> value {
|
.deref = +[]([[maybe_unused]] const value& v) -> value {
|
||||||
if constexpr ( detail::has_deref_op_kind<T> ) {
|
if constexpr ( detail::has_value_deref_traits<T> ) {
|
||||||
return value{*v.cast<T>()};
|
return value{*v.cast<T>()};
|
||||||
} else {
|
} else {
|
||||||
throw std::logic_error("value type doesn't have deref operator");
|
throw std::logic_error("value type doesn't have value deref traits");
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
.cderef = +[]([[maybe_unused]] const value& v) -> value {
|
.index = +[]([[maybe_unused]] const value& v, [[maybe_unused]] std::size_t index) -> value {
|
||||||
if constexpr ( detail::has_deref_op_kind<T> ) {
|
if constexpr ( detail::has_value_index_traits<T> ) {
|
||||||
return value{*v.cast<T>()};
|
return detail::value_index_traits<T>{}(v.cast<T>(), index);
|
||||||
} else {
|
} else {
|
||||||
throw std::logic_error("value type doesn't have deref operator");
|
throw std::logic_error("value type doesn't have value index traits");
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
.less = +[]([[maybe_unused]] const value& l, [[maybe_unused]] const value& r) -> bool {
|
.less = +[]([[maybe_unused]] const value& l, [[maybe_unused]] const value& r) -> bool {
|
||||||
if constexpr ( detail::has_less_op_kind<T> ) {
|
if constexpr ( detail::has_value_less_traits<T> ) {
|
||||||
return l.cast<T>() < r.cast<T>();
|
return detail::value_less_traits<T>{}(l.cast<T>(), r.cast<T>());
|
||||||
} else {
|
} else {
|
||||||
throw std::logic_error("value type doesn't have less operator");
|
throw std::logic_error("value type doesn't have value less traits");
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
.equals = +[]([[maybe_unused]] const value& l, [[maybe_unused]] const value& r) -> bool {
|
.equals = +[]([[maybe_unused]] const value& l, [[maybe_unused]] const value& r) -> bool {
|
||||||
if constexpr ( detail::has_equals_op_kind<T> ) {
|
if constexpr ( detail::has_value_equals_traits<T> ) {
|
||||||
return l.cast<T>() == r.cast<T>();
|
return detail::value_equals_traits<T>{}(l.cast<T>(), r.cast<T>());
|
||||||
} else {
|
} else {
|
||||||
throw std::logic_error("value type doesn't have equality operator");
|
throw std::logic_error("value type doesn't have value equals traits");
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -97,18 +104,18 @@ namespace meta_hpp
|
|||||||
},
|
},
|
||||||
|
|
||||||
.istream = +[]([[maybe_unused]] std::istream& is, [[maybe_unused]] value& v) -> std::istream& {
|
.istream = +[]([[maybe_unused]] std::istream& is, [[maybe_unused]] value& v) -> std::istream& {
|
||||||
if constexpr ( detail::has_istream_op_kind<T> ) {
|
if constexpr ( detail::has_value_istream_traits<T> ) {
|
||||||
return is >> v.cast<T>();
|
return detail::value_istream_traits<T>{}(is, v.cast<T>());
|
||||||
} else {
|
} else {
|
||||||
throw std::logic_error("value type doesn't have istream operator");
|
throw std::logic_error("value type doesn't have value istream traits");
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
.ostream = +[]([[maybe_unused]] std::ostream& os, [[maybe_unused]] const value& v) -> std::ostream& {
|
.ostream = +[]([[maybe_unused]] std::ostream& os, [[maybe_unused]] const value& v) -> std::ostream& {
|
||||||
if constexpr ( detail::has_ostream_op_kind<T> ) {
|
if constexpr ( detail::has_value_ostream_traits<T> ) {
|
||||||
return os << v.cast<T>();
|
return detail::value_ostream_traits<T>{}(os, v.cast<T>());
|
||||||
} else {
|
} else {
|
||||||
throw std::logic_error("value type doesn't have ostream operator");
|
throw std::logic_error("value type doesn't have value ostream traits");
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
@@ -181,16 +188,12 @@ namespace meta_hpp
|
|||||||
return traits_->cdata(*this);
|
return traits_->cdata(*this);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline value value::deref() {
|
inline value value::operator*() const {
|
||||||
return traits_->deref(*this);
|
return traits_->deref(*this);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline value value::deref() const {
|
inline value value::operator[](std::size_t index) const {
|
||||||
return traits_->cderef(*this);
|
return traits_->index(*this, index);
|
||||||
}
|
|
||||||
|
|
||||||
inline value value::cderef() const {
|
|
||||||
return traits_->cderef(*this);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template < typename T, typename Tp >
|
template < typename T, typename Tp >
|
||||||
|
|||||||
@@ -0,0 +1,52 @@
|
|||||||
|
/*******************************************************************************
|
||||||
|
* This file is part of the "https://github.com/blackmatov/meta.hpp"
|
||||||
|
* For conditions of distribution and use, see copyright notice in LICENSE.md
|
||||||
|
* Copyright (C) 2021, by Matvey Cherevko (blackmatov@gmail.com)
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "../../meta_base.hpp"
|
||||||
|
#include "../../meta_utilities.hpp"
|
||||||
|
|
||||||
|
namespace meta_hpp::detail
|
||||||
|
{
|
||||||
|
template < typename T >
|
||||||
|
struct value_deref_traits;
|
||||||
|
|
||||||
|
template < typename T >
|
||||||
|
concept has_value_deref_traits = requires(const T& v) {
|
||||||
|
{ value_deref_traits<T>{}(v) } -> stdex::convertible_to<value>;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace meta_hpp::detail
|
||||||
|
{
|
||||||
|
template < stdex::copy_constructible T >
|
||||||
|
struct value_deref_traits<T*> {
|
||||||
|
value operator()(T* v) const {
|
||||||
|
return value{*v};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template < stdex::copy_constructible T >
|
||||||
|
struct value_deref_traits<const T*> {
|
||||||
|
value operator()(const T* v) const {
|
||||||
|
return value{*v};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template < stdex::copy_constructible T >
|
||||||
|
struct value_deref_traits<std::shared_ptr<T>> {
|
||||||
|
value operator()(const std::shared_ptr<T>& v) const {
|
||||||
|
return value{*v};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template < stdex::copy_constructible T >
|
||||||
|
struct value_deref_traits<std::unique_ptr<T>> {
|
||||||
|
value operator()(const std::unique_ptr<T>& v) const {
|
||||||
|
return value{*v};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
/*******************************************************************************
|
||||||
|
* This file is part of the "https://github.com/blackmatov/meta.hpp"
|
||||||
|
* For conditions of distribution and use, see copyright notice in LICENSE.md
|
||||||
|
* Copyright (C) 2021, by Matvey Cherevko (blackmatov@gmail.com)
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "../../meta_base.hpp"
|
||||||
|
|
||||||
|
namespace meta_hpp::detail
|
||||||
|
{
|
||||||
|
template < typename T >
|
||||||
|
struct value_equals_traits;
|
||||||
|
|
||||||
|
template < typename T >
|
||||||
|
concept has_value_equals_traits = requires(const T& v) {
|
||||||
|
{ value_equals_traits<T>{}(v, v) } -> stdex::convertible_to<bool>;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace meta_hpp::detail
|
||||||
|
{
|
||||||
|
template < typename T >
|
||||||
|
requires requires(const T& v) {
|
||||||
|
{ v == v } -> stdex::convertible_to<bool>;
|
||||||
|
}
|
||||||
|
struct value_equals_traits<T> {
|
||||||
|
bool operator()(const T& l, const T& r) const {
|
||||||
|
return l == r;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -0,0 +1,66 @@
|
|||||||
|
/*******************************************************************************
|
||||||
|
* This file is part of the "https://github.com/blackmatov/meta.hpp"
|
||||||
|
* For conditions of distribution and use, see copyright notice in LICENSE.md
|
||||||
|
* Copyright (C) 2021, by Matvey Cherevko (blackmatov@gmail.com)
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "../../meta_base.hpp"
|
||||||
|
#include "../../meta_utilities.hpp"
|
||||||
|
|
||||||
|
namespace meta_hpp::detail
|
||||||
|
{
|
||||||
|
template < typename T >
|
||||||
|
struct value_index_traits;
|
||||||
|
|
||||||
|
template < typename T >
|
||||||
|
concept has_value_index_traits = requires(const T& v, std::size_t i) {
|
||||||
|
{ value_index_traits<T>{}(v, i) } -> stdex::convertible_to<value>;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace meta_hpp::detail
|
||||||
|
{
|
||||||
|
template < stdex::copy_constructible T >
|
||||||
|
struct value_index_traits<T*> {
|
||||||
|
value operator()(T* v, std::size_t i) const {
|
||||||
|
return value{*(v + i)};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template < stdex::copy_constructible T >
|
||||||
|
struct value_index_traits<const T*> {
|
||||||
|
value operator()(const T* v, std::size_t i) const {
|
||||||
|
return value{*(v + i)};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template < stdex::copy_constructible T, std::size_t Size >
|
||||||
|
struct value_index_traits<std::array<T, Size>> {
|
||||||
|
value operator()(const std::array<T, Size>& v, std::size_t i) const {
|
||||||
|
return value{v[i]};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template < stdex::copy_constructible T, std::size_t Extent >
|
||||||
|
struct value_index_traits<std::span<T, Extent>> {
|
||||||
|
value operator()(const std::span<T, Extent>& v, std::size_t i) const {
|
||||||
|
return value{v[i]};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template < stdex::copy_constructible T, typename Traits, typename Allocator >
|
||||||
|
struct value_index_traits<std::basic_string<T, Traits, Allocator>> {
|
||||||
|
value operator()(const std::basic_string<T, Traits, Allocator>& v, std::size_t i) const {
|
||||||
|
return value{v[i]};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template < stdex::copy_constructible T, typename Allocator >
|
||||||
|
struct value_index_traits<std::vector<T, Allocator>> {
|
||||||
|
value operator()(const std::vector<T, Allocator>& v, std::size_t i) {
|
||||||
|
return value{v[i]};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
/*******************************************************************************
|
||||||
|
* This file is part of the "https://github.com/blackmatov/meta.hpp"
|
||||||
|
* For conditions of distribution and use, see copyright notice in LICENSE.md
|
||||||
|
* Copyright (C) 2021, by Matvey Cherevko (blackmatov@gmail.com)
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "../../meta_base.hpp"
|
||||||
|
|
||||||
|
namespace meta_hpp::detail
|
||||||
|
{
|
||||||
|
template < typename T >
|
||||||
|
struct value_istream_traits;
|
||||||
|
|
||||||
|
template < typename T >
|
||||||
|
concept has_value_istream_traits = requires(std::istream& is, T& v) {
|
||||||
|
{ value_istream_traits<T>{}(is, v) } -> stdex::convertible_to<std::istream&>;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace meta_hpp::detail
|
||||||
|
{
|
||||||
|
template < typename T >
|
||||||
|
requires requires(std::istream& is, T& v) {
|
||||||
|
{ is >> v } -> stdex::convertible_to<std::istream&>;
|
||||||
|
}
|
||||||
|
struct value_istream_traits<T> {
|
||||||
|
std::istream& operator()(std::istream& is, T& v) const {
|
||||||
|
return is >> v;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
33
headers/meta.hpp/meta_utilities/value_traits/less_traits.hpp
Normal file
33
headers/meta.hpp/meta_utilities/value_traits/less_traits.hpp
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
/*******************************************************************************
|
||||||
|
* This file is part of the "https://github.com/blackmatov/meta.hpp"
|
||||||
|
* For conditions of distribution and use, see copyright notice in LICENSE.md
|
||||||
|
* Copyright (C) 2021, by Matvey Cherevko (blackmatov@gmail.com)
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "../../meta_base.hpp"
|
||||||
|
|
||||||
|
namespace meta_hpp::detail
|
||||||
|
{
|
||||||
|
template < typename T >
|
||||||
|
struct value_less_traits;
|
||||||
|
|
||||||
|
template < typename T >
|
||||||
|
concept has_value_less_traits = requires(const T& v) {
|
||||||
|
{ value_less_traits<T>{}(v, v) } -> stdex::convertible_to<bool>;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace meta_hpp::detail
|
||||||
|
{
|
||||||
|
template < typename T >
|
||||||
|
requires requires(const T& v) {
|
||||||
|
{ v < v } -> stdex::convertible_to<bool>;
|
||||||
|
}
|
||||||
|
struct value_less_traits<T> {
|
||||||
|
bool operator()(const T& l, const T& r) const {
|
||||||
|
return l < r;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
/*******************************************************************************
|
||||||
|
* This file is part of the "https://github.com/blackmatov/meta.hpp"
|
||||||
|
* For conditions of distribution and use, see copyright notice in LICENSE.md
|
||||||
|
* Copyright (C) 2021, by Matvey Cherevko (blackmatov@gmail.com)
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "../../meta_base.hpp"
|
||||||
|
|
||||||
|
namespace meta_hpp::detail
|
||||||
|
{
|
||||||
|
template < typename T >
|
||||||
|
struct value_ostream_traits;
|
||||||
|
|
||||||
|
template < typename T >
|
||||||
|
concept has_value_ostream_traits = requires(std::ostream& is, const T& v) {
|
||||||
|
{ value_ostream_traits<T>{}(is, v) } -> stdex::convertible_to<std::ostream&>;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace meta_hpp::detail
|
||||||
|
{
|
||||||
|
template < typename T >
|
||||||
|
requires requires(std::ostream& os, const T& v) {
|
||||||
|
{ os << v } -> stdex::convertible_to<std::ostream&>;
|
||||||
|
}
|
||||||
|
struct value_ostream_traits<T> {
|
||||||
|
std::ostream& operator()(std::ostream& is, const T& v) const {
|
||||||
|
return is << v;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -1,15 +0,0 @@
|
|||||||
/*******************************************************************************
|
|
||||||
* This file is part of the "https://github.com/blackmatov/meta.hpp"
|
|
||||||
* For conditions of distribution and use, see copyright notice in LICENSE.md
|
|
||||||
* Copyright (C) 2021, by Matvey Cherevko (blackmatov@gmail.com)
|
|
||||||
******************************************************************************/
|
|
||||||
|
|
||||||
#include "../meta_manuals.hpp"
|
|
||||||
|
|
||||||
namespace
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_CASE("meta/meta_examples/references") {
|
|
||||||
namespace meta = meta_hpp;
|
|
||||||
}
|
|
||||||
@@ -10,6 +10,6 @@ namespace
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("meta/meta_examples/pointers") {
|
TEST_CASE("meta/meta_examples/values") {
|
||||||
namespace meta = meta_hpp;
|
namespace meta = meta_hpp;
|
||||||
}
|
}
|
||||||
@@ -56,7 +56,7 @@ TEST_CASE("meta/meta_states/evalue") {
|
|||||||
CHECK(evalue.get_value() == color::green);
|
CHECK(evalue.get_value() == color::green);
|
||||||
CHECK(evalue.get_value().get_type() == color_type);
|
CHECK(evalue.get_value().get_type() == color_type);
|
||||||
|
|
||||||
CHECK(evalue.get_underlying_value() == meta::detail::to_underlying(color::green));
|
CHECK(evalue.get_underlying_value() == meta::detail::stdex::to_underlying(color::green));
|
||||||
CHECK(evalue.get_underlying_value().get_type() == color_type.get_underlying_type());
|
CHECK(evalue.get_underlying_value().get_type() == color_type.get_underlying_type());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -90,7 +90,7 @@ TEST_CASE("meta/meta_types/enum_type") {
|
|||||||
const meta::evalue green_value = color_type.get_evalue("green");
|
const meta::evalue green_value = color_type.get_evalue("green");
|
||||||
REQUIRE(green_value);
|
REQUIRE(green_value);
|
||||||
CHECK(green_value.get_value() == color::green);
|
CHECK(green_value.get_value() == color::green);
|
||||||
CHECK(green_value.get_underlying_value() == meta::detail::to_underlying(color::green));
|
CHECK(green_value.get_underlying_value() == meta::detail::stdex::to_underlying(color::green));
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
@@ -107,7 +107,7 @@ TEST_CASE("meta/meta_types/enum_type") {
|
|||||||
const meta::evalue green_value = ecolor_type.get_evalue("green");
|
const meta::evalue green_value = ecolor_type.get_evalue("green");
|
||||||
REQUIRE(green_value);
|
REQUIRE(green_value);
|
||||||
CHECK(green_value.get_value() == ecolor_green);
|
CHECK(green_value.get_value() == ecolor_green);
|
||||||
CHECK(green_value.get_underlying_value() == meta::detail::to_underlying(ecolor_green));
|
CHECK(green_value.get_underlying_value() == meta::detail::stdex::to_underlying(ecolor_green));
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -354,20 +354,20 @@ TEST_CASE("meta/meta_utilities/value") {
|
|||||||
SUBCASE("deref") {
|
SUBCASE("deref") {
|
||||||
{
|
{
|
||||||
int i{42};
|
int i{42};
|
||||||
const meta::value v{meta::value{&i}.deref()};
|
const meta::value v{*meta::value{&i}};
|
||||||
CHECK(v.get_type() == meta::resolve_type<int>());
|
CHECK(v.get_type() == meta::resolve_type<int>());
|
||||||
CHECK(v.data() != &i);
|
CHECK(v.data() != &i);
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
const char i{42};
|
const char i{42};
|
||||||
const meta::value v{meta::value{&i}.deref()};
|
const meta::value v{*meta::value{&i}};
|
||||||
CHECK(v.get_type() == meta::resolve_type<char>());
|
CHECK(v.get_type() == meta::resolve_type<char>());
|
||||||
CHECK(v.data() != &i);
|
CHECK(v.data() != &i);
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
const int i{42};
|
const int i{42};
|
||||||
const int* const pi = &i;
|
const int* const pi = &i;
|
||||||
const meta::value v{meta::value{&pi}.deref()};
|
const meta::value v{*meta::value{&pi}};
|
||||||
CHECK(v.get_type() == meta::resolve_type<const int*>() );
|
CHECK(v.get_type() == meta::resolve_type<const int*>() );
|
||||||
CHECK(v.cast<const int*>() == pi);
|
CHECK(v.cast<const int*>() == pi);
|
||||||
}
|
}
|
||||||
@@ -379,10 +379,10 @@ TEST_CASE("meta/meta_utilities/value") {
|
|||||||
void* const& p3 = &i;
|
void* const& p3 = &i;
|
||||||
const void* const& p4 = &i;
|
const void* const& p4 = &i;
|
||||||
|
|
||||||
CHECK_THROWS(std::ignore = meta::value(p1).deref());
|
CHECK_THROWS(std::ignore = *meta::value(p1));
|
||||||
CHECK_THROWS(std::ignore = meta::value(p2).deref());
|
CHECK_THROWS(std::ignore = *meta::value(p2));
|
||||||
CHECK_THROWS(std::ignore = meta::value(p3).deref());
|
CHECK_THROWS(std::ignore = *meta::value(p3));
|
||||||
CHECK_THROWS(std::ignore = meta::value(p4).deref());
|
CHECK_THROWS(std::ignore = *meta::value(p4));
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
ivec2 v{1,2};
|
ivec2 v{1,2};
|
||||||
@@ -390,18 +390,77 @@ TEST_CASE("meta/meta_utilities/value") {
|
|||||||
CHECK(ivec2::move_ctor_counter == 0);
|
CHECK(ivec2::move_ctor_counter == 0);
|
||||||
CHECK(ivec2::copy_ctor_counter == 0);
|
CHECK(ivec2::copy_ctor_counter == 0);
|
||||||
|
|
||||||
meta::value vv1{vp.deref()};
|
meta::value vv1{*vp};
|
||||||
CHECK(ivec2::move_ctor_counter == 0);
|
CHECK(ivec2::move_ctor_counter == 0);
|
||||||
CHECK(ivec2::copy_ctor_counter == 1);
|
CHECK(ivec2::copy_ctor_counter == 1);
|
||||||
|
|
||||||
meta::value vv2{std::move(vp).deref()};
|
meta::value vv2{*std::move(vp)};
|
||||||
CHECK(ivec2::move_ctor_counter == 0);
|
CHECK(ivec2::move_ctor_counter == 0);
|
||||||
CHECK(ivec2::copy_ctor_counter == 2);
|
CHECK(ivec2::copy_ctor_counter == 2);
|
||||||
|
|
||||||
meta::value vv3{vp.cderef()};
|
meta::value vv3{*std::as_const(vp)};
|
||||||
CHECK(ivec2::move_ctor_counter == 0);
|
CHECK(ivec2::move_ctor_counter == 0);
|
||||||
CHECK(ivec2::copy_ctor_counter == 3);
|
CHECK(ivec2::copy_ctor_counter == 3);
|
||||||
}
|
}
|
||||||
|
{
|
||||||
|
meta::value v{std::make_shared<int>(42)};
|
||||||
|
CHECK(*v == 42);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("meta/meta_utilities/value/arrays") {
|
||||||
|
namespace meta = meta_hpp;
|
||||||
|
|
||||||
|
SUBCASE("int[3]") {
|
||||||
|
int arr[3]{1,2,3};
|
||||||
|
meta::value v{arr};
|
||||||
|
CHECK(v.get_type() == meta::resolve_type<int*>());
|
||||||
|
CHECK(v[0] == 1);
|
||||||
|
CHECK(v[1] == 2);
|
||||||
|
CHECK(v[2] == 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
SUBCASE("const int[3]") {
|
||||||
|
const int arr[3]{1,2,3};
|
||||||
|
meta::value v{arr};
|
||||||
|
CHECK(v.get_type() == meta::resolve_type<const int*>());
|
||||||
|
CHECK(v[0] == 1);
|
||||||
|
CHECK(v[1] == 2);
|
||||||
|
CHECK(v[2] == 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
SUBCASE("std::array") {
|
||||||
|
meta::value v{std::array{1,2,3}};
|
||||||
|
CHECK(v.get_type() == meta::resolve_type<std::array<int, 3>>());
|
||||||
|
CHECK(v[0] == 1);
|
||||||
|
CHECK(v[1] == 2);
|
||||||
|
CHECK(v[2] == 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
SUBCASE("std::string") {
|
||||||
|
meta::value v{std::string{"hi!"}};
|
||||||
|
CHECK(v.get_type() == meta::resolve_type<std::string>());
|
||||||
|
CHECK(v[0] == 'h');
|
||||||
|
CHECK(v[1] == 'i');
|
||||||
|
CHECK(v[2] == '!');
|
||||||
|
}
|
||||||
|
|
||||||
|
SUBCASE("std::span") {
|
||||||
|
std::vector arr{1,2,3};
|
||||||
|
meta::value v{std::span{arr}};
|
||||||
|
CHECK(v.get_type() == meta::resolve_type<std::span<int>>());
|
||||||
|
CHECK(v[0] == 1);
|
||||||
|
CHECK(v[1] == 2);
|
||||||
|
CHECK(v[2] == 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
SUBCASE("std::vector") {
|
||||||
|
const meta::value v{std::vector{1,2,3}};
|
||||||
|
CHECK(v.get_type() == meta::resolve_type<std::vector<int>>());
|
||||||
|
CHECK(v[0] == 1);
|
||||||
|
CHECK(v[1] == 2);
|
||||||
|
CHECK(v[2] == 3);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user