start again from scratch

This commit is contained in:
BlackMATov
2021-08-20 15:17:31 +07:00
parent a9cfa77744
commit 6edfa34379
76 changed files with 5 additions and 9574 deletions

View File

@@ -20,18 +20,13 @@ target_include_directories(${PROJECT_NAME} INTERFACE headers)
target_compile_options(${PROJECT_NAME}
INTERFACE
$<$<CXX_COMPILER_ID:MSVC>:
/wd4702>
>
INTERFACE
$<$<CXX_COMPILER_ID:GNU>:
>
INTERFACE
$<$<OR:$<CXX_COMPILER_ID:Clang>,$<CXX_COMPILER_ID:AppleClang>>:
-Wno-c++98-compat-pedantic
-Wno-covered-switch-default
-Wno-ctad-maybe-unsupported
-Wno-exit-time-destructors
-Wno-padded
-Wno-poison-system-directories
-Wno-shadow
-Wno-unknown-warning-option
-Wno-weak-vtables>)
>)
if(BUILD_AS_STANDALONE)
option(BUILD_WITH_UNTESTS "Build with unit tests" ON)

View File

@@ -7,7 +7,3 @@
#pragma once
#include "meta_fwd.hpp"
#include "meta_infos.hpp"
#include "meta_registry.hpp"
#include "meta_types.hpp"
#include "meta_utilities.hpp"

View File

@@ -6,169 +6,6 @@
#pragma once
#include <algorithm>
#include <any>
#include <array>
#include <atomic>
#include <cassert>
#include <cstddef>
#include <cstdint>
#include <cstring>
#include <functional>
#include <initializer_list>
#include <iosfwd>
#include <map>
#include <memory>
#include <optional>
#include <stdexcept>
#include <string_view>
#include <string>
#include <tuple>
#include <type_traits>
#include <utility>
#include <variant>
#include <vector>
#include <enum.hpp/enum.hpp>
#include <enum.hpp/enum_bitflags.hpp>
#include <kari.hpp/kari.hpp>
namespace meta_hpp
{
template < typename Enum >
using bitflags = enum_hpp::bitflags::bitflags<Enum>;
}
namespace meta_hpp
{
class base_info;
class class_info;
class ctor_info;
class data_info;
class enum_info;
class evalue_info;
class function_info;
class member_info;
class method_info;
class namespace_info;
}
namespace meta_hpp
{
template < typename Base > class base_;
template < typename Class > class class_;
template < typename... Args > class ctor_;
class data_;
template < typename Enum > class enum_;
template < typename Enum > class evalue_;
template < typename Function > class function_;
template < typename Member > class member_;
template < typename Method > class method_;
class namespace_;
}
namespace meta_hpp
{
class type_id;
class arithmetic_type;
class array_type;
class base_type;
class class_type;
class ctor_type;
class enum_type;
class function_type;
class member_type;
class method_type;
class pointer_type;
class reference_type;
class void_type;
}
namespace meta_hpp
{
class arg;
class inst;
class value;
}
namespace meta_hpp
{
template < typename K, typename V >
using info_map = std::map<K, V, std::less<>>;
using base_info_map = info_map<type_id, base_info>;
using class_info_map = info_map<std::string, class_info>;
using ctor_info_map = info_map<type_id, ctor_info>;
using data_info_map = info_map<std::string, data_info>;
using enum_info_map = info_map<std::string, enum_info>;
using evalue_info_map = info_map<std::string, evalue_info>;
using function_info_map = info_map<std::string, function_info>;
using member_info_map = info_map<std::string, member_info>;
using method_info_map = info_map<std::string, method_info>;
using namespace_info_map = info_map<std::string, namespace_info>;
}
namespace meta_hpp
{
template < typename... Args >
struct typename_arg_t {};
template < typename... Args >
inline constexpr typename_arg_t<Args...> typename_arg{};
}
namespace meta_hpp::stdex
{
template < typename T >
struct is_bounded_array: std::false_type {};
template < typename T, std::size_t N >
struct is_bounded_array<T[N]>: std::true_type {};
template < typename T >
inline constexpr bool is_bounded_array_v = is_bounded_array<T>::value;
template < typename T >
struct is_unbounded_array: std::false_type {};
template < typename T >
struct is_unbounded_array<T[]>: std::true_type {};
template < typename T >
inline constexpr bool is_unbounded_array_v = is_unbounded_array<T>::value;
template < typename T >
struct remove_cvref {
using type = std::remove_cv_t<std::remove_reference_t<T>>;
};
template < typename T >
using remove_cvref_t = typename remove_cvref<T>::type;
template < typename Enum >
constexpr std::underlying_type_t<Enum> to_underlying(Enum e) noexcept {
return static_cast<std::underlying_type_t<Enum>>(e);
}
}
namespace meta_hpp::detail
{
template < typename K, typename V, typename C, typename A, typename K2, typename U >
V find_or(const std::map<K, V, C, A>& src, K2&& key, U&& def) {
if ( auto iter = src.find(std::forward<K2>(key)); iter != src.end() ) {
return iter->second;
}
return std::forward<U>(def);
}
template < typename K, typename V, typename C, typename A, typename K2 >
V find_or_default(const std::map<K, V, C, A>& src, K2&& key) {
return find_or(src, std::forward<K2>(key), V{});
}
template < typename K, typename V, typename C, typename A, typename K2, typename V2, typename F >
void merge_with(std::map<K, V, C, A>& dst, K2&& key, V2&& value, F&& f) {
if ( auto iter = dst.find(key); iter != dst.end() ) {
std::invoke(std::forward<F>(f), iter->second, std::forward<V2>(value));
} else {
dst.emplace(std::forward<K2>(key), std::forward<V2>(value));
}
}
}

View File

@@ -1,20 +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)
******************************************************************************/
#pragma once
#include "meta_fwd.hpp"
#include "meta_infos/base_info.hpp"
#include "meta_infos/class_info.hpp"
#include "meta_infos/ctor_info.hpp"
#include "meta_infos/data_info.hpp"
#include "meta_infos/enum_info.hpp"
#include "meta_infos/evalue_info.hpp"
#include "meta_infos/function_info.hpp"
#include "meta_infos/member_info.hpp"
#include "meta_infos/method_info.hpp"
#include "meta_infos/namespace_info.hpp"

View File

@@ -1,11 +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)
******************************************************************************/
#pragma once
#include "../meta_fwd.hpp"
#include "../meta_types.hpp"
#include "../meta_utilities.hpp"

View File

@@ -1,93 +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)
******************************************************************************/
#pragma once
#include "_infos_fwd.hpp"
#include "data_info.hpp"
namespace meta_hpp
{
class base_info final {
public:
base_info() = default;
void merge(const base_info& other);
explicit operator bool() const noexcept;
const base_type& type() const noexcept;
public:
template < typename F >
void visit(F&& f) const;
template < typename F >
void each_data(F&& f) const;
data_info get_data_by_name(std::string_view name) const noexcept;
private:
template < typename Base > friend class base_;
template < typename Base, typename Derived >
explicit base_info(typename_arg_t<Base>, typename_arg_t<Derived>);
private:
struct state;
std::shared_ptr<state> state_;
};
}
namespace meta_hpp
{
struct base_info::state final {
base_type type;
data_info_map datas;
};
}
namespace meta_hpp
{
inline void base_info::merge(const base_info& other) {
(void)other;
///TODO: implme
}
inline base_info::operator bool() const noexcept {
return !!state_;
}
inline const base_type& base_info::type() const noexcept {
return state_->type;
}
}
namespace meta_hpp
{
template < typename F >
void base_info::visit(F&& f) const {
each_data(f);
}
template < typename F >
void base_info::each_data(F&& f) const {
for ( auto&& name_info : state_->datas ) {
std::invoke(f, name_info.second);
}
}
inline data_info base_info::get_data_by_name(std::string_view name) const noexcept {
return detail::find_or_default(state_->datas, name);
}
}
namespace meta_hpp
{
template < typename Base, typename Derived >
base_info::base_info(typename_arg_t<Base>, typename_arg_t<Derived>)
: state_{std::make_shared<state>(state{
base_type{typename_arg<Base>, typename_arg<Derived>},
{}
})} {}
}

View File

@@ -1,289 +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)
******************************************************************************/
#pragma once
#include "_infos_fwd.hpp"
#include "base_info.hpp"
#include "ctor_info.hpp"
#include "data_info.hpp"
#include "enum_info.hpp"
#include "function_info.hpp"
#include "member_info.hpp"
#include "method_info.hpp"
namespace meta_hpp
{
class class_info final {
public:
class_info() = default;
void merge(const class_info& other);
explicit operator bool() const noexcept;
const std::string& name() const noexcept;
const class_type& type() const noexcept;
template < typename Base >
bool is_derived_from() const;
bool is_derived_from(any_type base) const noexcept;
template < typename... Args >
ctor_info get_ctor_by_args() const noexcept;
template < std::size_t N >
ctor_info get_ctor_by_args(const std::array<any_type, N>& args) const noexcept;
ctor_info get_ctor_by_args(const std::vector<any_type>& args) const noexcept;
ctor_info get_ctor_by_args(std::initializer_list<any_type> args) const noexcept;
public:
template < typename F >
void visit(F&& f) const;
template < typename F >
void each_base(F&& f) const;
template < typename F >
void each_class(F&& f) const;
template < typename F >
void each_ctor(F&& f) const;
template < typename F >
void each_data(F&& f) const;
template < typename F >
void each_enum(F&& f) const;
template < typename F >
void each_function(F&& f) const;
template < typename F >
void each_member(F&& f) const;
template < typename F >
void each_method(F&& f) const;
class_info get_class_by_name(std::string_view name) const noexcept;
data_info get_data_by_name(std::string_view name) const noexcept;
enum_info get_enum_by_name(std::string_view name) const noexcept;
function_info get_function_by_name(std::string_view name) const noexcept;
member_info get_member_by_name(std::string_view name) const noexcept;
method_info get_method_by_name(std::string_view name) const noexcept;
private:
template < typename Class > friend class class_;
template < typename Class >
explicit class_info(typename_arg_t<Class>, std::string name);
private:
struct state;
std::shared_ptr<state> state_;
};
}
namespace meta_hpp
{
struct class_info::state final {
std::string name;
class_type type;
base_info_map bases;
class_info_map classes;
ctor_info_map ctors;
data_info_map datas;
enum_info_map enums;
function_info_map functions;
member_info_map members;
method_info_map methods;
};
}
namespace meta_hpp
{
inline void class_info::merge(const class_info& other) {
(void)other;
///TODO: implme
}
inline class_info::operator bool() const noexcept {
return !!state_;
}
inline const std::string& class_info::name() const noexcept {
return state_->name;
}
inline const class_type& class_info::type() const noexcept {
return state_->type;
}
template < typename Base >
bool class_info::is_derived_from() const {
return class_info::is_derived_from(type_db::get<Base>());
}
inline bool class_info::is_derived_from(any_type base) const noexcept {
for ( auto&& id_info : state_->bases ) {
if ( base == id_info.second.type().base_class_type() ) {
return true;
}
}
return false;
}
template < typename... Args >
ctor_info class_info::get_ctor_by_args() const noexcept {
std::array<any_type, sizeof...(Args)> args{type_db::get<Args>()...};
return get_ctor_by_args(args);
}
template < std::size_t N >
ctor_info class_info::get_ctor_by_args(const std::array<any_type, N>& args) const noexcept {
for ( auto&& id_info : state_->ctors ) {
const std::vector<any_type>& ctor_args =
id_info.second.type().argument_types();
if ( args.size() == ctor_args.size()
&& std::equal(args.begin(), args.end(), ctor_args.begin()) )
{
return id_info.second;
}
}
return ctor_info{};
}
inline ctor_info class_info::get_ctor_by_args(const std::vector<any_type>& args) const noexcept {
for ( auto&& id_info : state_->ctors ) {
const std::vector<any_type>& ctor_args =
id_info.second.type().argument_types();
if ( args.size() == ctor_args.size()
&& std::equal(args.begin(), args.end(), ctor_args.begin()) )
{
return id_info.second;
}
}
return ctor_info{};
}
inline ctor_info class_info::get_ctor_by_args(std::initializer_list<any_type> args) const noexcept {
for ( auto&& id_info : state_->ctors ) {
const std::vector<any_type>& ctor_args =
id_info.second.type().argument_types();
if ( args.size() == ctor_args.size()
&& std::equal(args.begin(), args.end(), ctor_args.begin()) )
{
return id_info.second;
}
}
return ctor_info{};
}
}
namespace meta_hpp
{
template < typename F >
void class_info::visit(F&& f) const {
each_base(f);
each_class(f);
each_ctor(f);
each_data(f);
each_enum(f);
each_function(f);
each_member(f);
each_method(f);
}
template < typename F >
void class_info::each_base(F&& f) const {
for ( auto&& id_info : state_->bases ) {
std::invoke(f, id_info.second);
}
}
template < typename F >
void class_info::each_class(F&& f) const {
for ( auto&& name_info : state_->classes ) {
std::invoke(f, name_info.second);
}
}
template < typename F >
void class_info::each_ctor(F&& f) const {
for ( auto&& id_info : state_->ctors ) {
std::invoke(f, id_info.second);
}
}
template < typename F >
void class_info::each_data(F&& f) const {
for ( auto&& name_info : state_->datas ) {
std::invoke(f, name_info.second);
}
}
template < typename F >
void class_info::each_enum(F&& f) const {
for ( auto&& name_info : state_->enums ) {
std::invoke(f, name_info.second);
}
}
template < typename F >
void class_info::each_function(F&& f) const {
for ( auto&& name_info : state_->functions ) {
std::invoke(f, name_info.second);
}
}
template < typename F >
void class_info::each_member(F&& f) const {
for ( auto&& name_info : state_->members ) {
std::invoke(f, name_info.second);
}
}
template < typename F >
void class_info::each_method(F&& f) const {
for ( auto&& name_info : state_->methods ) {
std::invoke(f, name_info.second);
}
}
inline class_info class_info::get_class_by_name(std::string_view name) const noexcept {
return detail::find_or_default(state_->classes, name);
}
inline data_info class_info::get_data_by_name(std::string_view name) const noexcept {
return detail::find_or_default(state_->datas, name);
}
inline enum_info class_info::get_enum_by_name(std::string_view name) const noexcept {
return detail::find_or_default(state_->enums, name);
}
inline function_info class_info::get_function_by_name(std::string_view name) const noexcept {
return detail::find_or_default(state_->functions, name);
}
inline member_info class_info::get_member_by_name(std::string_view name) const noexcept {
return detail::find_or_default(state_->members, name);
}
inline method_info class_info::get_method_by_name(std::string_view name) const noexcept {
return detail::find_or_default(state_->methods, name);
}
}
namespace meta_hpp
{
template < typename Class >
inline class_info::class_info(typename_arg_t<Class>, std::string name)
: state_{std::make_shared<state>(state{
std::move(name),
type_db::get<Class>().template as<class_type>(),
{}, {}, {}, {}, {}, {}, {}, {}
})} {}
}

View File

@@ -1,204 +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)
******************************************************************************/
#pragma once
#include "_infos_fwd.hpp"
#include "data_info.hpp"
namespace meta_hpp
{
class ctor_info final {
public:
ctor_info() = default;
void merge(const ctor_info& other);
explicit operator bool() const noexcept;
const ctor_type& type() const noexcept;
template < typename... Args >
value invoke(Args&&... args) const;
template < typename... Args >
bool is_invocable_with() const noexcept;
public:
template < typename F >
void visit(F&& f) const;
template < typename F >
void each_data(F&& f) const;
data_info get_data_by_name(std::string_view name) const noexcept;
private:
template < typename... Args > friend class ctor_;
template < typename Class, typename... Args >
explicit ctor_info(typename_arg_t<Class>, typename_arg_t<Args...>);
private:
struct state;
std::shared_ptr<state> state_;
};
}
namespace meta_hpp::detail
{
using ctor_invoke = std::function<value(const arg*, std::size_t)>;
template < typename Class, typename... Args, std::size_t... Is >
value raw_ctor_invoke_impl(
const arg* args,
std::index_sequence<Is...>)
{
using ct = ctor_traits<Class, Args...>;
using class_type = typename ct::class_type;
using argument_types = typename ct::argument_types;
if ( !(... && (args + Is)->can_cast_to<std::tuple_element_t<Is, argument_types>>()) ) {
throw std::logic_error("an attempt to call a ctor with an incorrect argument types");
}
class_type class_value{(args + Is)->cast<std::tuple_element_t<Is, argument_types>>()...};
return value{std::forward<class_type>(class_value)};
}
template < typename Class, typename... Args >
value raw_ctor_invoke(
const arg* args,
std::size_t arg_count)
{
using ct = ctor_traits<Class, Args...>;
if ( arg_count != ct::arity ) {
throw std::logic_error("an attempt to call a ctor with an incorrect arity");
}
return raw_ctor_invoke_impl<Class, Args...>(
args,
std::make_index_sequence<ct::arity>());
}
template < typename Class, typename... Args >
ctor_invoke make_ctor_invoke() {
using namespace std::placeholders;
return std::bind(&raw_ctor_invoke<Class, Args...>, _1, _2);
}
}
namespace meta_hpp::detail
{
using ctor_is_invocable_with = std::function<bool(const arg_base*, std::size_t)>;
template < typename Class, typename... Args, std::size_t... Is >
bool raw_ctor_is_invocable_with_impl(
const arg_base* arg_bases,
std::index_sequence<Is...>)
{
using ct = ctor_traits<Class, Args...>;
using argument_types = typename ct::argument_types;
return (... && (arg_bases + Is)->can_cast_to<std::tuple_element_t<Is, argument_types>>() );
}
template < typename Class, typename... Args >
bool raw_ctor_is_invocable_with(
const arg_base* arg_bases,
std::size_t arg_count)
{
using ct = ctor_traits<Class, Args...>;
if ( arg_count != ct::arity ) {
return false;
}
return raw_ctor_is_invocable_with_impl<Class, Args...>(
arg_bases,
std::make_index_sequence<ct::arity>());
}
template < typename Class, typename... Args >
ctor_is_invocable_with make_ctor_is_invocable_with() {
using namespace std::placeholders;
return std::bind(&raw_ctor_is_invocable_with<Class, Args...>, _1, _2);
}
}
namespace meta_hpp
{
struct ctor_info::state final {
ctor_type type;
data_info_map datas;
detail::ctor_invoke invoke;
detail::ctor_is_invocable_with is_invocable_with;
};
}
namespace meta_hpp
{
inline void ctor_info::merge(const ctor_info& other) {
(void)other;
///TODO: implme
}
inline ctor_info::operator bool() const noexcept {
return !!state_;
}
inline const ctor_type& ctor_info::type() const noexcept {
return state_->type;
}
template < typename... Args >
value ctor_info::invoke(Args&&... args) const {
if constexpr ( sizeof...(Args) > 0 ) {
std::array<arg, sizeof...(Args)> vargs{arg{std::forward<Args>(args)}...};
return state_->invoke(vargs.data(), vargs.size());
} else {
return state_->invoke(nullptr, 0);
}
}
template < typename... Args >
bool ctor_info::is_invocable_with() const noexcept {
if constexpr ( sizeof...(Args) > 0 ) {
std::array<arg_base, sizeof...(Args)> arg_bases{arg_base{typename_arg<Args>}...};
return state_->is_invocable_with(arg_bases.data(), arg_bases.size());
} else {
return state_->is_invocable_with(nullptr, 0);
}
}
}
namespace meta_hpp
{
template < typename F >
void ctor_info::visit(F&& f) const {
each_data(f);
}
template < typename F >
void ctor_info::each_data(F&& f) const {
for ( auto&& name_info : state_->datas ) {
std::invoke(f, name_info.second);
}
}
inline data_info ctor_info::get_data_by_name(std::string_view name) const noexcept {
return detail::find_or_default(state_->datas, name);
}
}
namespace meta_hpp
{
template < typename Class, typename... Args >
ctor_info::ctor_info(typename_arg_t<Class>, typename_arg_t<Args...>)
: state_{std::make_shared<state>(state{
ctor_type{typename_arg<Class>, typename_arg<Args...>},
{},
detail::make_ctor_invoke<Class, Args...>(),
detail::make_ctor_is_invocable_with<Class, Args...>(),
})} {}
}

View File

@@ -1,96 +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)
******************************************************************************/
#pragma once
#include "_infos_fwd.hpp"
namespace meta_hpp
{
class data_info final {
public:
data_info() = default;
void merge(const data_info& other);
explicit operator bool() const noexcept;
const std::string& name() const noexcept;
const class value& value() const noexcept;
public:
template < typename F >
void visit(F&& f) const;
template < typename F >
void each_data(F&& f) const;
data_info get_data_by_name(std::string_view name) const noexcept;
private:
friend class data_;
explicit data_info(std::string name, class value value);
private:
struct state;
std::shared_ptr<state> state_;
};
}
namespace meta_hpp
{
struct data_info::state final {
std::string name;
class value value;
data_info_map datas;
};
}
namespace meta_hpp
{
inline void data_info::merge(const data_info& other) {
(void)other;
///TODO: implme
}
inline data_info::operator bool() const noexcept {
return !!state_;
}
inline const std::string& data_info::name() const noexcept {
return state_->name;
}
inline const class value& data_info::value() const noexcept {
return state_->value;
}
}
namespace meta_hpp
{
template < typename F >
void data_info::visit(F&& f) const {
each_data(f);
}
template < typename F >
void data_info::each_data(F&& f) const {
for ( auto&& name_info : state_->datas ) {
std::invoke(f, name_info.second);
}
}
inline data_info data_info::get_data_by_name(std::string_view name) const noexcept {
return detail::find_or_default(state_->datas, name);
}
}
namespace meta_hpp
{
inline data_info::data_info(std::string name, class value value)
: state_{std::make_shared<state>(state{
std::move(name),
std::move(value),
{}
})} {}
}

View File

@@ -1,118 +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)
******************************************************************************/
#pragma once
#include "_infos_fwd.hpp"
#include "data_info.hpp"
#include "evalue_info.hpp"
namespace meta_hpp
{
class enum_info final {
public:
enum_info() = default;
void merge(const enum_info& other);
explicit operator bool() const noexcept;
const std::string& name() const noexcept;
const enum_type& type() const noexcept;
public:
template < typename F >
void visit(F&& f) const;
template < typename F >
void each_data(F&& f) const;
template < typename F >
void each_evalue(F&& f) const;
data_info get_data_by_name(std::string_view name) const noexcept;
evalue_info get_evalue_by_name(std::string_view name) const noexcept;
private:
template < typename Enum > friend class enum_;
template < typename Enum >
explicit enum_info(typename_arg_t<Enum>, std::string name);
private:
struct state;
std::shared_ptr<state> state_;
};
}
namespace meta_hpp
{
struct enum_info::state final {
std::string name;
enum_type type;
data_info_map datas;
evalue_info_map evalues;
};
}
namespace meta_hpp
{
inline void enum_info::merge(const enum_info& other) {
(void)other;
///TODO: implme
}
inline enum_info::operator bool() const noexcept {
return !!state_;
}
inline const std::string& enum_info::name() const noexcept {
return state_->name;
}
inline const enum_type& enum_info::type() const noexcept {
return state_->type;
}
}
namespace meta_hpp
{
template < typename F >
void enum_info::visit(F&& f) const {
each_data(f);
each_evalue(f);
}
template < typename F >
void enum_info::each_data(F&& f) const {
for ( auto&& name_info : state_->datas ) {
std::invoke(f, name_info.second);
}
}
template < typename F >
void enum_info::each_evalue(F&& f) const {
for ( auto&& name_info : state_->evalues ) {
std::invoke(f, name_info.second);
}
}
inline data_info enum_info::get_data_by_name(std::string_view name) const noexcept {
return detail::find_or_default(state_->datas, name);
}
inline evalue_info enum_info::get_evalue_by_name(std::string_view name) const noexcept {
return detail::find_or_default(state_->evalues, name);
}
}
namespace meta_hpp
{
template < typename Enum >
enum_info::enum_info(typename_arg_t<Enum>, std::string name)
: state_{std::make_shared<state>(state{
std::move(name),
type_db::get<Enum>().template as<enum_type>(),
{}, {}
})} {}
}

View File

@@ -1,100 +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)
******************************************************************************/
#pragma once
#include "_infos_fwd.hpp"
#include "data_info.hpp"
namespace meta_hpp
{
class evalue_info final {
public:
evalue_info() = default;
void merge(const evalue_info& other);
explicit operator bool() const noexcept;
const std::string& name() const noexcept;
const class value& value() const noexcept;
public:
template < typename F >
void visit(F&& f) const;
template < typename F >
void each_data(F&& f) const;
data_info get_data_by_name(std::string_view name) const noexcept;
private:
template < typename Enum > friend class evalue_;
template < typename Enum >
explicit evalue_info(std::string name, Enum value);
private:
struct state;
std::shared_ptr<state> state_;
};
}
namespace meta_hpp
{
struct evalue_info::state final {
std::string name;
class value value;
data_info_map datas;
};
}
namespace meta_hpp
{
inline void evalue_info::merge(const evalue_info& other) {
(void)other;
///TODO: implme
}
inline evalue_info::operator bool() const noexcept {
return !!state_;
}
inline const std::string& evalue_info::name() const noexcept {
return state_->name;
}
inline const class value& evalue_info::value() const noexcept {
return state_->value;
}
}
namespace meta_hpp
{
template < typename F >
void evalue_info::visit(F&& f) const {
each_data(f);
}
template < typename F >
void evalue_info::each_data(F&& f) const {
for ( auto&& name_info : state_->datas ) {
std::invoke(f, name_info.second);
}
}
inline data_info evalue_info::get_data_by_name(std::string_view name) const noexcept {
return detail::find_or_default(state_->datas, name);
}
}
namespace meta_hpp
{
template < typename Enum >
evalue_info::evalue_info(std::string name, Enum value)
: state_{std::make_shared<state>(state{
std::move(name),
std::move(value),
{}
})} {}
}

View File

@@ -1,221 +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)
******************************************************************************/
#pragma once
#include "_infos_fwd.hpp"
#include "data_info.hpp"
namespace meta_hpp
{
class function_info final {
public:
function_info() = default;
void merge(const function_info& other);
explicit operator bool() const noexcept;
const std::string& name() const noexcept;
const function_type& type() const noexcept;
template < typename... Args >
std::optional<value> invoke(Args&&... args) const;
template < typename... Args >
bool is_invocable_with() const noexcept;
public:
template < typename F >
void visit(F&& f) const;
template < typename F >
void each_data(F&& f) const;
data_info get_data_by_name(std::string_view name) const noexcept;
private:
template < typename Function > friend class function_;
template < typename Function >
explicit function_info(std::string name, Function function);
private:
struct state;
std::shared_ptr<state> state_;
};
}
namespace meta_hpp::detail
{
using function_invoke = std::function<std::optional<value>(const arg*, std::size_t)>;
template < typename Function, std::size_t... Is >
std::optional<value> raw_function_invoke_impl(
Function function,
const arg* args,
std::index_sequence<Is...>)
{
using ft = function_pointer_traits<Function>;
using return_type = typename ft::return_type;
using argument_types = typename ft::argument_types;
if ( !(... && (args + Is)->can_cast_to<std::tuple_element_t<Is, argument_types>>()) ) {
throw std::logic_error("an attempt to call a function with an incorrect argument types");
}
if constexpr ( std::is_void_v<return_type> ) {
std::invoke(function,
(args + Is)->cast<std::tuple_element_t<Is, argument_types>>()...);
return std::nullopt;
} else {
return_type return_value{std::invoke(function,
(args + Is)->cast<std::tuple_element_t<Is, argument_types>>()...)};
return value{std::forward<return_type>(return_value)};
}
}
template < typename Function >
std::optional<value> raw_function_invoke(
Function function,
const arg* args,
std::size_t arg_count)
{
using ft = function_pointer_traits<Function>;
if ( arg_count != ft::arity ) {
throw std::logic_error("an attempt to call a function with an incorrect arity");
}
return raw_function_invoke_impl<Function>(
function,
args,
std::make_index_sequence<ft::arity>());
}
template < typename Function >
function_invoke make_function_invoke(Function function) {
using namespace std::placeholders;
return std::bind(&raw_function_invoke<Function>, function, _1, _2);
}
}
namespace meta_hpp::detail
{
using function_is_invocable_with = std::function<bool(const arg_base*, std::size_t)>;
template < typename Function, std::size_t... Is >
bool raw_function_is_invocable_with_impl(
const arg_base* arg_bases,
std::index_sequence<Is...>)
{
using ft = function_pointer_traits<Function>;
using argument_types = typename ft::argument_types;
return (... && (arg_bases + Is)->can_cast_to<std::tuple_element_t<Is, argument_types>>() );
}
template < typename Function >
bool raw_function_is_invocable_with(
const arg_base* arg_bases,
std::size_t arg_count)
{
using ft = function_pointer_traits<Function>;
if ( arg_count != ft::arity ) {
return false;
}
return raw_function_is_invocable_with_impl<Function>(
arg_bases,
std::make_index_sequence<ft::arity>());
}
template < typename Function >
function_is_invocable_with make_function_is_invocable_with() {
using namespace std::placeholders;
return std::bind(&raw_function_is_invocable_with<Function>, _1, _2);
}
}
namespace meta_hpp
{
struct function_info::state final {
std::string name;
function_type type;
data_info_map datas;
detail::function_invoke invoke;
detail::function_is_invocable_with is_invocable_with;
};
}
namespace meta_hpp
{
inline void function_info::merge(const function_info& other) {
(void)other;
///TODO: implme
}
inline function_info::operator bool() const noexcept {
return !!state_;
}
inline const std::string& function_info::name() const noexcept {
return state_->name;
}
inline const function_type& function_info::type() const noexcept {
return state_->type;
}
template < typename... Args >
std::optional<value> function_info::invoke(Args&&... args) const {
if constexpr ( sizeof...(Args) > 0 ) {
std::array<arg, sizeof...(Args)> vargs{arg{std::forward<Args>(args)}...};
return state_->invoke(vargs.data(), vargs.size());
} else {
return state_->invoke(nullptr, 0);
}
}
template < typename... Args >
bool function_info::is_invocable_with() const noexcept {
if constexpr ( sizeof...(Args) > 0 ) {
std::array<arg_base, sizeof...(Args)> arg_bases{arg_base{typename_arg<Args>}...};
return state_->is_invocable_with(arg_bases.data(), arg_bases.size());
} else {
return state_->is_invocable_with(nullptr, 0);
}
}
}
namespace meta_hpp
{
template < typename F >
void function_info::visit(F&& f) const {
each_data(f);
}
template < typename F >
void function_info::each_data(F&& f) const {
for ( auto&& name_info : state_->datas ) {
std::invoke(f, name_info.second);
}
}
inline data_info function_info::get_data_by_name(std::string_view name) const noexcept {
return detail::find_or_default(state_->datas, name);
}
}
namespace meta_hpp
{
template < typename Function >
function_info::function_info(std::string name, Function function)
: state_{std::make_shared<state>(state{
std::move(name),
type_db::get<Function>().template as<function_type>(),
{},
detail::make_function_invoke<Function>(function),
detail::make_function_is_invocable_with<Function>(),
})} {}
}

View File

@@ -1,181 +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)
******************************************************************************/
#pragma once
#include "_infos_fwd.hpp"
#include "data_info.hpp"
namespace meta_hpp
{
class member_info final {
public:
member_info() = default;
void merge(const member_info& other);
explicit operator bool() const noexcept;
const std::string& name() const noexcept;
const member_type& type() const noexcept;
template < typename Instance >
value get(Instance&& instance) const;
template < typename Instance, typename Value >
void set(Instance&& instance, Value&& value) const;
public:
template < typename F >
void visit(F&& f) const;
template < typename F >
void each_data(F&& f) const;
data_info get_data_by_name(std::string_view name) const noexcept;
private:
template < typename Member > friend class member_;
template < typename Member >
explicit member_info(std::string name, Member instance);
private:
struct state;
std::shared_ptr<state> state_;
};
}
namespace meta_hpp::detail
{
using member_getter = std::function<value(const inst&)>;
using member_setter = std::function<void(const inst&, const arg&)>;
template < typename Member >
value raw_member_getter(Member member, const inst& inst) {
using mt = member_pointer_traits<Member>;
using class_type = typename mt::class_type;
using value_type = typename mt::value_type;
using qualified_type = const class_type;
if ( !inst.can_cast_to<qualified_type>() ) {
throw std::logic_error("an attempt to get a member with an incorrect instance type");
}
value_type return_value{std::invoke(member, inst.cast<qualified_type>())};
return value{std::forward<value_type>(return_value)};
}
template < typename Member >
void raw_member_setter([[maybe_unused]] Member member, const inst& inst, const arg& arg) {
using mt = member_pointer_traits<Member>;
using class_type = typename mt::class_type;
using value_type = typename mt::value_type;
using qualified_type = class_type;
if constexpr ( !std::is_const_v<value_type> ) {
if ( inst.is_const() ) {
throw std::logic_error("an attempt to set a member with an const instance type");
}
if ( !inst.can_cast_to<qualified_type>() ) {
throw std::logic_error("an attempt to set a member with an incorrect instance type");
}
if ( !arg.can_cast_to<value_type>() ) {
throw std::logic_error("an attempt to set a member with an incorrect argument type");
}
std::invoke(member, inst.cast<qualified_type>()) = arg.cast<value_type>();
} else {
throw std::logic_error("an attempt to set a constant member");
}
}
template < typename Member >
member_getter make_member_getter(Member member) {
using namespace std::placeholders;
return std::bind(&raw_member_getter<Member>, member, _1);
}
template < typename Member >
member_setter make_member_setter(Member member) {
using namespace std::placeholders;
return std::bind(&raw_member_setter<Member>, member, _1, _2);
}
}
namespace meta_hpp
{
struct member_info::state final {
std::string name;
member_type type;
data_info_map datas;
detail::member_getter getter;
detail::member_setter setter;
};
}
namespace meta_hpp
{
inline void member_info::merge(const member_info& other) {
(void)other;
///TODO: implme
}
inline member_info::operator bool() const noexcept {
return !!state_;
}
inline const std::string& member_info::name() const noexcept {
return state_->name;
}
inline const member_type& member_info::type() const noexcept {
return state_->type;
}
template < typename Instance >
value member_info::get(Instance&& instance) const {
return state_->getter(inst{std::forward<Instance>(instance)});
}
template < typename Instance, typename Value >
void member_info::set(Instance&& instance, Value&& value) const {
state_->setter(inst{std::forward<Instance>(instance)}, arg{std::forward<Value>(value)});
}
}
namespace meta_hpp
{
template < typename F >
void member_info::visit(F&& f) const {
each_data(f);
}
template < typename F >
void member_info::each_data(F&& f) const {
for ( auto&& name_info : state_->datas ) {
std::invoke(f, name_info.second);
}
}
inline data_info member_info::get_data_by_name(std::string_view name) const noexcept {
return detail::find_or_default(state_->datas, name);
}
}
namespace meta_hpp
{
template < typename Member >
member_info::member_info(std::string name, Member member)
: state_{std::make_shared<state>(state{
std::move(name),
type_db::get<Member>().template as<member_type>(),
{},
detail::make_member_getter<Member>(member),
detail::make_member_setter<Member>(member),
})} {}
}

View File

@@ -1,237 +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)
******************************************************************************/
#pragma once
#include "_infos_fwd.hpp"
#include "data_info.hpp"
namespace meta_hpp
{
class method_info final {
public:
method_info() = default;
void merge(const method_info& other);
explicit operator bool() const noexcept;
const std::string& name() const noexcept;
const method_type& type() const noexcept;
template < typename Instance, typename... Args >
std::optional<value> invoke(Instance&& instance, Args&&... args) const;
template < typename Inst, typename... Args >
bool is_invocable_with() const noexcept;
public:
template < typename F >
void visit(F&& f) const;
template < typename F >
void each_data(F&& f) const;
data_info get_data_by_name(std::string_view name) const noexcept;
private:
template < typename Method > friend class method_;
template < typename Method >
explicit method_info(std::string name, Method method);
private:
struct state;
std::shared_ptr<state> state_;
};
}
namespace meta_hpp::detail
{
using method_invoke = std::function<std::optional<value>(const inst&, const arg*, std::size_t)>;
template < typename Method, std::size_t... Is >
std::optional<value> raw_method_invoke_impl(
Method method,
const inst& inst,
const arg* args,
std::index_sequence<Is...>)
{
using mt = method_pointer_traits<Method>;
using return_type = typename mt::return_type;
using qualified_type = typename mt::qualified_type;
using argument_types = typename mt::argument_types;
if ( !inst.can_cast_to<qualified_type>() ) {
throw std::logic_error("an attempt to call a method with an incorrect instance type");
}
if ( !(... && (args + Is)->can_cast_to<std::tuple_element_t<Is, argument_types>>()) ) {
throw std::logic_error("an attempt to call a method with an incorrect argument types");
}
if constexpr ( std::is_void_v<return_type> ) {
std::invoke(method,
inst.cast<qualified_type>(),
(args + Is)->cast<std::tuple_element_t<Is, argument_types>>()...);
return std::nullopt;
} else {
return_type return_value{std::invoke(method,
inst.cast<qualified_type>(),
(args + Is)->cast<std::tuple_element_t<Is, argument_types>>()...)};
return value{std::forward<return_type>(return_value)};
}
}
template < typename Method >
std::optional<value> raw_method_invoke(
Method method,
const inst& inst,
const arg* args,
std::size_t arg_count)
{
using mt = method_pointer_traits<Method>;
if ( arg_count != mt::arity ) {
throw std::logic_error("an attempt to call a method with an incorrect arity");
}
return raw_method_invoke_impl<Method>(
method,
inst,
args,
std::make_index_sequence<mt::arity>());
}
template < typename Method >
method_invoke make_method_invoke(Method method) {
using namespace std::placeholders;
return std::bind(&raw_method_invoke<Method>, method, _1, _2, _3);
}
}
namespace meta_hpp::detail
{
using method_is_invocable_with = std::function<bool(const inst_base&, const arg_base*, std::size_t)>;
template < typename Method, std::size_t... Is >
bool raw_method_is_invocable_with_impl(
const inst_base& inst_base,
const arg_base* arg_bases,
std::index_sequence<Is...>)
{
using mt = method_pointer_traits<Method>;
using qualified_type = typename mt::qualified_type;
using argument_types = typename mt::argument_types;
return inst_base.can_cast_to<qualified_type>()
&& (... && (arg_bases + Is)->can_cast_to<std::tuple_element_t<Is, argument_types>>() );
}
template < typename Method >
bool raw_method_is_invocable_with(
const inst_base& inst_base,
const arg_base* arg_bases,
std::size_t arg_count)
{
using mt = method_pointer_traits<Method>;
if ( arg_count != mt::arity ) {
return false;
}
return raw_method_is_invocable_with_impl<Method>(
inst_base,
arg_bases,
std::make_index_sequence<mt::arity>());
}
template < typename Method >
method_is_invocable_with make_method_is_invocable_with() {
using namespace std::placeholders;
return std::bind(&raw_method_is_invocable_with<Method>, _1, _2, _3);
}
}
namespace meta_hpp
{
struct method_info::state final {
std::string name;
method_type type;
data_info_map datas;
detail::method_invoke invoke;
detail::method_is_invocable_with is_invocable_with;
};
}
namespace meta_hpp
{
inline void method_info::merge(const method_info& other) {
(void)other;
///TODO: implme
}
inline method_info::operator bool() const noexcept {
return !!state_;
}
inline const std::string& method_info::name() const noexcept {
return state_->name;
}
inline const method_type& method_info::type() const noexcept {
return state_->type;
}
template < typename Instance, typename... Args >
std::optional<value> method_info::invoke(Instance&& instance, Args&&... args) const {
if constexpr ( sizeof...(Args) > 0 ) {
std::array<arg, sizeof...(Args)> vargs{arg{std::forward<Args>(args)}...};
return state_->invoke(inst{std::forward<Instance>(instance)}, vargs.data(), vargs.size());
} else {
return state_->invoke(inst{std::forward<Instance>(instance)}, nullptr, 0);
}
}
template < typename Inst, typename... Args >
bool method_info::is_invocable_with() const noexcept {
if constexpr ( sizeof...(Args) > 0 ) {
std::array<arg_base, sizeof...(Args)> arg_bases{arg_base{typename_arg<Args>}...};
return state_->is_invocable_with(inst_base{typename_arg<Inst>}, arg_bases.data(), arg_bases.size());
} else {
return state_->is_invocable_with(inst_base{typename_arg<Inst>}, nullptr, 0);
}
}
}
namespace meta_hpp
{
template < typename F >
void method_info::visit(F&& f) const {
each_data(f);
}
template < typename F >
void method_info::each_data(F&& f) const {
for ( auto&& name_info : state_->datas ) {
std::invoke(f, name_info.second);
}
}
inline data_info method_info::get_data_by_name(std::string_view name) const noexcept {
return detail::find_or_default(state_->datas, name);
}
}
namespace meta_hpp
{
template < typename Method >
method_info::method_info(std::string name, Method method)
: state_{std::make_shared<state>(state{
std::move(name),
type_db::get<Method>().template as<method_type>(),
{},
detail::make_method_invoke<Method>(method),
detail::make_method_is_invocable_with<Method>(),
})} {}
}

View File

@@ -1,162 +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)
******************************************************************************/
#pragma once
#include "_infos_fwd.hpp"
#include "class_info.hpp"
#include "data_info.hpp"
#include "enum_info.hpp"
#include "function_info.hpp"
namespace meta_hpp
{
class namespace_info final {
public:
namespace_info() = default;
void merge(const namespace_info& other);
explicit operator bool() const noexcept;
const std::string& name() const noexcept;
public:
template < typename F >
void visit(F&& f) const;
template < typename F >
void each_class(F&& f) const;
template < typename F >
void each_data(F&& f) const;
template < typename F >
void each_enum(F&& f) const;
template < typename F >
void each_function(F&& f) const;
template < typename F >
void each_namespace(F&& f) const;
class_info get_class_by_name(std::string_view name) const noexcept;
data_info get_data_by_name(std::string_view name) const noexcept;
enum_info get_enum_by_name(std::string_view name) const noexcept;
function_info get_function_by_name(std::string_view name) const noexcept;
namespace_info get_namespace_by_name(std::string_view name) const noexcept;
private:
friend class namespace_;
explicit namespace_info(std::string name);
private:
struct state;
std::shared_ptr<state> state_;
};
}
namespace meta_hpp
{
struct namespace_info::state final {
std::string name;
class_info_map classes;
data_info_map datas;
enum_info_map enums;
function_info_map functions;
namespace_info_map namespaces;
};
}
namespace meta_hpp
{
inline void namespace_info::merge(const namespace_info& other) {
(void)other;
///TODO: implme
}
inline namespace_info::operator bool() const noexcept {
return !!state_;
}
inline const std::string& namespace_info::name() const noexcept {
return state_->name;
}
}
namespace meta_hpp
{
template < typename F >
void namespace_info::visit(F&& f) const {
each_class(f);
each_data(f);
each_enum(f);
each_function(f);
each_namespace(f);
}
template < typename F >
void namespace_info::each_class(F&& f) const {
for ( auto&& name_info : state_->classes ) {
std::invoke(f, name_info.second);
}
}
template < typename F >
void namespace_info::each_data(F&& f) const {
for ( auto&& name_info : state_->datas ) {
std::invoke(f, name_info.second);
}
}
template < typename F >
void namespace_info::each_enum(F&& f) const {
for ( auto&& name_info : state_->enums ) {
std::invoke(f, name_info.second);
}
}
template < typename F >
void namespace_info::each_function(F&& f) const {
for ( auto&& name_info : state_->functions ) {
std::invoke(f, name_info.second);
}
}
template < typename F >
void namespace_info::each_namespace(F&& f) const {
for ( auto&& name_info : state_->namespaces ) {
std::invoke(f, name_info.second);
}
}
inline class_info namespace_info::get_class_by_name(std::string_view name) const noexcept {
return detail::find_or_default(state_->classes, name);
}
inline data_info namespace_info::get_data_by_name(std::string_view name) const noexcept {
return detail::find_or_default(state_->datas, name);
}
inline enum_info namespace_info::get_enum_by_name(std::string_view name) const noexcept {
return detail::find_or_default(state_->enums, name);
}
inline function_info namespace_info::get_function_by_name(std::string_view name) const noexcept {
return detail::find_or_default(state_->functions, name);
}
inline namespace_info namespace_info::get_namespace_by_name(std::string_view name) const noexcept {
return detail::find_or_default(state_->namespaces, name);
}
}
namespace meta_hpp
{
inline namespace_info::namespace_info(std::string name)
: state_{std::make_shared<state>(state{
std::move(name),
{}, {}, {}, {}, {}
})} {}
}

View File

@@ -1,211 +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)
******************************************************************************/
#pragma once
#include "meta_fwd.hpp"
#include "meta_infos.hpp"
#include "meta_registry/base_.hpp"
#include "meta_registry/class_.hpp"
#include "meta_registry/ctor_.hpp"
#include "meta_registry/data_.hpp"
#include "meta_registry/enum_.hpp"
#include "meta_registry/evalue_.hpp"
#include "meta_registry/function_.hpp"
#include "meta_registry/member_.hpp"
#include "meta_registry/method_.hpp"
#include "meta_registry/namespace_.hpp"
namespace meta_hpp
{
class registry final {
public:
registry() = default;
class_info get_class_by_path(std::string_view path) const noexcept;
data_info get_data_by_path(std::string_view path) const noexcept;
enum_info get_enum_by_path(std::string_view path) const noexcept;
evalue_info get_evalue_by_path(std::string_view path) const noexcept;
function_info get_function_by_path(std::string_view path) const noexcept;
member_info get_member_by_path(std::string_view path) const noexcept;
method_info get_method_by_path(std::string_view path) const noexcept;
namespace_info get_namespace_by_path(std::string_view path) const noexcept;
public:
template < typename... Internals >
registry& operator()(Internals&&... internals);
private:
template < typename Class >
void add_(const std::string& prefix, const class_<Class>& internal);
void add_(const std::string& prefix, const data_& internal);
template < typename Enum >
void add_(const std::string& prefix, const enum_<Enum>& internal);
template < typename Function >
void add_(const std::string& prefix, const function_<Function>& internal);
void add_(const std::string& prefix, const namespace_& internal);
void add_(const std::string& prefix, ...) = delete;
private:
struct add_info_f;
void add_info_(const std::string& prefix, const base_info& info);
void add_info_(const std::string& prefix, const class_info& info);
void add_info_(const std::string& prefix, const ctor_info& info);
void add_info_(const std::string& prefix, const data_info& info);
void add_info_(const std::string& prefix, const enum_info& info);
void add_info_(const std::string& prefix, const evalue_info& info);
void add_info_(const std::string& prefix, const function_info& info);
void add_info_(const std::string& prefix, const member_info& info);
void add_info_(const std::string& prefix, const method_info& info);
void add_info_(const std::string& prefix, const namespace_info& info);
void add_info_(const std::string& prefix, ...) = delete;
private:
class_info_map classes_;
data_info_map datas_;
enum_info_map enums_;
evalue_info_map evalues_;
function_info_map functions_;
member_info_map members_;
method_info_map methods_;
namespace_info_map namespaces_;
};
}
namespace meta_hpp
{
inline class_info registry::get_class_by_path(std::string_view path) const noexcept {
return detail::find_or_default(classes_, path);
}
inline data_info registry::get_data_by_path(std::string_view path) const noexcept {
return detail::find_or_default(datas_, path);
}
inline enum_info registry::get_enum_by_path(std::string_view path) const noexcept {
return detail::find_or_default(enums_, path);
}
inline evalue_info registry::get_evalue_by_path(std::string_view path) const noexcept {
return detail::find_or_default(evalues_, path);
}
inline function_info registry::get_function_by_path(std::string_view path) const noexcept {
return detail::find_or_default(functions_, path);
}
inline member_info registry::get_member_by_path(std::string_view path) const noexcept {
return detail::find_or_default(members_, path);
}
inline method_info registry::get_method_by_path(std::string_view path) const noexcept {
return detail::find_or_default(methods_, path);
}
inline namespace_info registry::get_namespace_by_path(std::string_view path) const noexcept {
return detail::find_or_default(namespaces_, path);
}
}
namespace meta_hpp
{
template < typename... Internals >
inline registry& registry::operator()(Internals&&... internals) {
(add_(std::string{}, std::forward<Internals>(internals)), ...);
return *this;
}
}
namespace meta_hpp
{
template < typename Class >
inline void registry::add_(const std::string& prefix, const class_<Class>& internal) {
add_info_(prefix, internal.make_info());
}
inline void registry::add_(const std::string& prefix, const data_& internal) {
add_info_(prefix, internal.make_info());
}
template < typename Enum >
inline void registry::add_(const std::string& prefix, const enum_<Enum>& internal) {
add_info_(prefix, internal.make_info());
}
template < typename Function >
inline void registry::add_(const std::string& prefix, const function_<Function>& internal) {
add_info_(prefix, internal.make_info());
}
inline void registry::add_(const std::string& prefix, const namespace_& internal) {
add_info_(prefix, internal.make_info());
}
}
namespace meta_hpp
{
struct registry::add_info_f final {
template < typename Info >
void operator()(registry& self, const std::string& prefix, Info&& info) const {
self.add_info_(prefix, std::forward<Info>(info));
}
};
inline void registry::add_info_(const std::string& prefix, const base_info& info) {
(void)prefix;
(void)info;
}
inline void registry::add_info_(const std::string& prefix, const class_info& info) {
std::string name = prefix.empty() ? info.name() : prefix + "::" + info.name();
info.visit(kari_hpp::curry(add_info_f{}, std::ref(*this), name));
detail::merge_with(classes_, name, info, &class_info::merge);
}
inline void registry::add_info_(const std::string& prefix, const ctor_info& info) {
(void)prefix;
(void)info;
}
inline void registry::add_info_(const std::string& prefix, const data_info& info) {
std::string name = prefix.empty() ? info.name() : prefix + "::" + info.name();
info.visit(kari_hpp::curry(add_info_f{}, std::ref(*this), name));
detail::merge_with(datas_, name, info, &data_info::merge);
}
inline void registry::add_info_(const std::string& prefix, const enum_info& info) {
std::string name = prefix.empty() ? info.name() : prefix + "::" + info.name();
info.visit(kari_hpp::curry(add_info_f{}, std::ref(*this), name));
detail::merge_with(enums_, name, info, &enum_info::merge);
}
inline void registry::add_info_(const std::string& prefix, const evalue_info& info) {
std::string name = prefix.empty() ? info.name() : prefix + "::" + info.name();
info.visit(kari_hpp::curry(add_info_f{}, std::ref(*this), name));
detail::merge_with(evalues_, name, info, &evalue_info::merge);
}
inline void registry::add_info_(const std::string& prefix, const function_info& info) {
std::string name = prefix.empty() ? info.name() : prefix + "::" + info.name();
info.visit(kari_hpp::curry(add_info_f{}, std::ref(*this), name));
detail::merge_with(functions_, name, info, &function_info::merge);
}
inline void registry::add_info_(const std::string& prefix, const member_info& info) {
std::string name = prefix.empty() ? info.name() : prefix + "::" + info.name();
info.visit(kari_hpp::curry(add_info_f{}, std::ref(*this), name));
detail::merge_with(members_, name, info, &member_info::merge);
}
inline void registry::add_info_(const std::string& prefix, const method_info& info) {
std::string name = prefix.empty() ? info.name() : prefix + "::" + info.name();
info.visit(kari_hpp::curry(add_info_f{}, std::ref(*this), name));
detail::merge_with(methods_, name, info, &method_info::merge);
}
inline void registry::add_info_(const std::string& prefix, const namespace_info& info) {
std::string name = prefix.empty() ? info.name() : prefix + "::" + info.name();
info.visit(kari_hpp::curry(add_info_f{}, std::ref(*this), name));
detail::merge_with(namespaces_, name, info, &namespace_info::merge);
}
}

View File

@@ -1,11 +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)
******************************************************************************/
#pragma once
#include "../meta_fwd.hpp"
#include "../meta_infos.hpp"
#include "../meta_utilities.hpp"

View File

@@ -1,58 +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)
******************************************************************************/
#pragma once
#include "_registry_fwd.hpp"
#include "data_.hpp"
namespace meta_hpp
{
template < typename Base >
class base_ final {
public:
explicit base_() = default;
template < typename Derived >
base_info make_info() const;
public:
template < typename... Internals >
base_& operator()(Internals&&...internals);
private:
void add_(const data_& internal);
void add_(...) = delete;
private:
data_info_map datas_;
};
}
namespace meta_hpp
{
template < typename Base >
template < typename Derived >
base_info base_<Base>::make_info() const {
base_info info{typename_arg<Base>, typename_arg<Derived>};
info.state_->datas.insert(datas_.begin(), datas_.end());
return info;
}
template < typename Base >
template < typename... Internals >
base_<Base>& base_<Base>::operator()(Internals&&...internals) {
(add_(std::forward<Internals>(internals)), ...);
return *this;
}
}
namespace meta_hpp
{
template < typename Base >
void base_<Base>::add_(const data_& internal) {
auto info = internal.make_info();
detail::merge_with(datas_, info.name(), info, &data_info::merge);
}
}

View File

@@ -1,144 +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)
******************************************************************************/
#pragma once
#include "_registry_fwd.hpp"
#include "base_.hpp"
#include "ctor_.hpp"
#include "data_.hpp"
#include "enum_.hpp"
#include "function_.hpp"
#include "member_.hpp"
#include "method_.hpp"
namespace meta_hpp
{
template < typename Class >
class class_ final {
public:
explicit class_(std::string name);
class_info make_info() const;
public:
template < typename... Internals >
class_& operator()(Internals&&...internals);
private:
template < typename Base >
void add_(const base_<Base>& internal);
template < typename Class2 >
void add_(const class_<Class2>& internal);
template < typename... Args >
void add_(const ctor_<Args...>& internal);
void add_(const data_& internal);
template < typename Enum >
void add_(const enum_<Enum>& internal);
template < typename Function >
void add_(const function_<Function>& internal);
template < typename Member >
void add_(const member_<Member>& internal);
template < typename Method >
void add_(const method_<Method>& internal);
void add_(...) = delete;
private:
std::string name_;
base_info_map bases_;
class_info_map classes_;
ctor_info_map ctors_;
data_info_map datas_;
enum_info_map enums_;
function_info_map functions_;
member_info_map members_;
method_info_map methods_;
};
}
namespace meta_hpp
{
template < typename Class >
class_<Class>::class_(std::string name)
: name_{std::move(name)} {}
template < typename Class >
class_info class_<Class>::make_info() const {
class_info info{typename_arg<Class>, name_};
info.state_->bases.insert(bases_.begin(), bases_.end());
info.state_->classes.insert(classes_.begin(), classes_.end());
info.state_->ctors.insert(ctors_.begin(), ctors_.end());
info.state_->datas.insert(datas_.begin(), datas_.end());
info.state_->enums.insert(enums_.begin(), enums_.end());
info.state_->functions.insert(functions_.begin(), functions_.end());
info.state_->members.insert(members_.begin(), members_.end());
info.state_->methods.insert(methods_.begin(), methods_.end());
return info;
}
template < typename Class >
template < typename... Internals >
class_<Class>& class_<Class>::operator()(Internals&&...internals) {
(add_(std::forward<Internals>(internals)), ...);
return *this;
}
}
namespace meta_hpp
{
template < typename Class >
template < typename Base >
void class_<Class>::add_(const base_<Base>& internal) {
auto info = internal.template make_info<Class>();
detail::merge_with(bases_, info.type().id(), info, &base_info::merge);
}
template < typename Class >
template < typename Class2 >
void class_<Class>::add_(const class_<Class2>& internal) {
auto info = internal.make_info();
detail::merge_with(classes_, info.name(), info, &class_info::merge);
}
template < typename Class >
template < typename... Args >
void class_<Class>::add_(const ctor_<Args...>& internal) {
auto info = internal.template make_info<Class>();
detail::merge_with(ctors_, info.type().id(), info, &ctor_info::merge);
}
template < typename Class >
void class_<Class>::add_(const data_& internal) {
auto info = internal.make_info();
detail::merge_with(datas_, info.name(), info, &data_info::merge);
}
template < typename Class >
template < typename Enum >
void class_<Class>::add_(const enum_<Enum>& internal) {
auto info = internal.make_info();
detail::merge_with(enums_, info.name(), info, &enum_info::merge);
}
template < typename Class >
template < typename Function >
void class_<Class>::add_(const function_<Function>& internal) {
auto info = internal.make_info();
detail::merge_with(functions_, info.name(), info, &function_info::merge);
}
template < typename Class >
template < typename Member >
void class_<Class>::add_(const member_<Member>& internal) {
auto info = internal.make_info();
detail::merge_with(members_, info.name(), info, &member_info::merge);
}
template < typename Class >
template < typename Method >
void class_<Class>::add_(const method_<Method>& internal) {
auto info = internal.make_info();
detail::merge_with(methods_, info.name(), info, &method_info::merge);
}
}

View File

@@ -1,58 +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)
******************************************************************************/
#pragma once
#include "_registry_fwd.hpp"
#include "data_.hpp"
namespace meta_hpp
{
template < typename... Args >
class ctor_ final {
public:
explicit ctor_() = default;
template < typename Class >
ctor_info make_info() const;
public:
template < typename... Internals >
ctor_& operator()(Internals&&...internals);
private:
void add_(const data_& internal);
void add_(...) = delete;
private:
data_info_map datas_;
};
}
namespace meta_hpp
{
template < typename... Args >
template < typename Class >
ctor_info ctor_<Args...>::make_info() const {
ctor_info info{typename_arg<Class>, typename_arg<Args...>};
info.state_->datas.insert(datas_.begin(), datas_.end());
return info;
}
template < typename... Args >
template < typename... Internals >
ctor_<Args...>& ctor_<Args...>::operator()(Internals&&...internals) {
(add_(std::forward<Internals>(internals)), ...);
return *this;
}
}
namespace meta_hpp
{
template < typename... Args >
void ctor_<Args...>::add_(const data_& internal) {
auto info = internal.make_info();
detail::merge_with(datas_, info.name(), info, &data_info::merge);
}
}

View File

@@ -1,58 +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)
******************************************************************************/
#pragma once
#include "_registry_fwd.hpp"
namespace meta_hpp
{
class data_ final {
public:
template < typename T >
explicit data_(std::string name, T&& value);
data_info make_info() const;
public:
template < typename... Internals >
data_& operator()(Internals&&...internals);
private:
void add_(const data_& internal);
void add_(...) = delete;
private:
std::string name_;
class value value_;
data_info_map datas_;
};
}
namespace meta_hpp
{
template < typename T >
data_::data_(std::string name, T&& value)
: name_{std::move(name)}
, value_{std::forward<T>(value)} {}
inline data_info data_::make_info() const {
data_info info{name_, value_};
info.state_->datas.insert(datas_.begin(), datas_.end());
return info;
}
template < typename... Internals >
data_& data_::operator()(Internals&&...internals) {
(add_(std::forward<Internals>(internals)), ...);
return *this;
}
}
namespace meta_hpp
{
inline void data_::add_(const data_& internal) {
auto info = internal.make_info();
detail::merge_with(datas_, info.name(), info, &data_info::merge);
}
}

View File

@@ -1,71 +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)
******************************************************************************/
#pragma once
#include "_registry_fwd.hpp"
#include "data_.hpp"
#include "evalue_.hpp"
namespace meta_hpp
{
template < typename Enum >
class enum_ final {
public:
explicit enum_(std::string name);
enum_info make_info() const;
public:
template < typename... Internals >
enum_& operator()(Internals&&...internals);
private:
void add_(const data_& internal);
void add_(const evalue_<Enum>& internal);
void add_(...) = delete;
private:
std::string name_;
data_info_map datas_;
evalue_info_map evalues_;
};
}
namespace meta_hpp
{
template < typename Enum >
enum_<Enum>::enum_(std::string name)
: name_{std::move(name)} {}
template < typename Enum >
enum_info enum_<Enum>::make_info() const {
enum_info info{typename_arg<Enum>, name_};
info.state_->datas.insert(datas_.begin(), datas_.end());
info.state_->evalues.insert(evalues_.begin(), evalues_.end());
return info;
}
template < typename Enum >
template < typename... Internals >
enum_<Enum>& enum_<Enum>::operator()(Internals&&...internals) {
(add_(std::forward<Internals>(internals)), ...);
return *this;
}
}
namespace meta_hpp
{
template < typename Enum >
void enum_<Enum>::add_(const data_& internal) {
auto info = internal.make_info();
detail::merge_with(datas_, info.name(), info, &data_info::merge);
}
template < typename Enum >
void enum_<Enum>::add_(const evalue_<Enum>& internal) {
auto info = internal.make_info();
detail::merge_with(evalues_, info.name(), info, &evalue_info::merge);
}
}

View File

@@ -1,63 +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)
******************************************************************************/
#pragma once
#include "_registry_fwd.hpp"
#include "data_.hpp"
namespace meta_hpp
{
template < typename Enum >
class evalue_ final {
public:
explicit evalue_(std::string name, Enum value);
evalue_info make_info() const;
public:
template < typename... Internals >
evalue_& operator()(Internals&&...internals);
private:
void add_(const data_& internal);
void add_(...) = delete;
private:
std::string name_;
Enum value_;
data_info_map datas_;
};
}
namespace meta_hpp
{
template < typename Enum >
evalue_<Enum>::evalue_(std::string name, Enum value)
: name_{std::move(name)}
, value_{std::move(value)} {}
template < typename Enum >
evalue_info evalue_<Enum>::make_info() const {
evalue_info info{name_, value_};
info.state_->datas.insert(datas_.begin(), datas_.end());
return info;
}
template < typename Enum >
template < typename... Internals >
evalue_<Enum>& evalue_<Enum>::operator()(Internals&&...internals) {
(add_(std::forward<Internals>(internals)), ...);
return *this;
}
}
namespace meta_hpp
{
template < typename Enum >
void evalue_<Enum>::add_(const data_& internal) {
auto info = internal.make_info();
detail::merge_with(datas_, info.name(), info, &data_info::merge);
}
}

View File

@@ -1,63 +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)
******************************************************************************/
#pragma once
#include "_registry_fwd.hpp"
#include "data_.hpp"
namespace meta_hpp
{
template < typename Function >
class function_ final {
public:
explicit function_(std::string name, Function instance);
function_info make_info() const;
public:
template < typename... Internals >
function_& operator()(Internals&&...internals);
private:
void add_(const data_& internal);
void add_(...) = delete;
private:
std::string name_;
Function instance_;
data_info_map datas_;
};
}
namespace meta_hpp
{
template < typename Function >
function_<Function>::function_(std::string name, Function instance)
: name_{std::move(name)}
, instance_{std::move(instance)} {}
template < typename Function >
function_info function_<Function>::make_info() const {
function_info info{name_, instance_};
info.state_->datas.insert(datas_.begin(), datas_.end());
return info;
}
template < typename Function >
template < typename... Internals >
function_<Function>& function_<Function>::operator()(Internals&&...internals) {
(add_(std::forward<Internals>(internals)), ...);
return *this;
}
}
namespace meta_hpp
{
template < typename Function >
void function_<Function>::add_(const data_& internal) {
auto info = internal.make_info();
detail::merge_with(datas_, info.name(), info, &data_info::merge);
}
}

View File

@@ -1,63 +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)
******************************************************************************/
#pragma once
#include "_registry_fwd.hpp"
#include "data_.hpp"
namespace meta_hpp
{
template < typename Member >
class member_ final {
public:
explicit member_(std::string name, Member instance);
member_info make_info() const;
public:
template < typename... Internals >
member_& operator()(Internals&&...internals);
private:
void add_(const data_& internal);
void add_(...) = delete;
private:
std::string name_;
Member instance_;
data_info_map datas_;
};
}
namespace meta_hpp
{
template < typename Member >
member_<Member>::member_(std::string name, Member instance)
: name_{std::move(name)}
, instance_{std::move(instance)} {}
template < typename Member >
member_info member_<Member>::make_info() const {
member_info info{name_, instance_};
info.state_->datas.insert(datas_.begin(), datas_.end());
return info;
}
template < typename Member >
template < typename... Internals >
member_<Member>& member_<Member>::operator()(Internals&&...internals) {
(add_(std::forward<Internals>(internals)), ...);
return *this;
}
}
namespace meta_hpp
{
template < typename Member >
void member_<Member>::add_(const data_& internal) {
auto info = internal.make_info();
detail::merge_with(datas_, info.name(), info, &data_info::merge);
}
}

View File

@@ -1,63 +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)
******************************************************************************/
#pragma once
#include "_registry_fwd.hpp"
#include "data_.hpp"
namespace meta_hpp
{
template < typename Method >
class method_ final {
public:
explicit method_(std::string name, Method instance);
method_info make_info() const;
public:
template < typename... Internals >
method_& operator()(Internals&&...internals);
private:
void add_(const data_& internal);
void add_(...) = delete;
private:
std::string name_;
Method instance_;
data_info_map datas_;
};
}
namespace meta_hpp
{
template < typename Method >
method_<Method>::method_(std::string name, Method instance)
: name_{std::move(name)}
, instance_{std::move(instance)} {}
template < typename Method >
method_info method_<Method>::make_info() const {
method_info info{name_, instance_};
info.state_->datas.insert(datas_.begin(), datas_.end());
return info;
}
template < typename Method >
template < typename... Internals >
method_<Method>& method_<Method>::operator()(Internals&&...internals) {
(add_(std::forward<Internals>(internals)), ...);
return *this;
}
}
namespace meta_hpp
{
template < typename Method >
void method_<Method>::add_(const data_& internal) {
auto info = internal.make_info();
detail::merge_with(datas_, info.name(), info, &data_info::merge);
}
}

View File

@@ -1,97 +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)
******************************************************************************/
#pragma once
#include "_registry_fwd.hpp"
#include "class_.hpp"
#include "data_.hpp"
#include "enum_.hpp"
#include "function_.hpp"
namespace meta_hpp
{
class namespace_ final {
public:
explicit namespace_(std::string name);
namespace_info make_info() const;
public:
template < typename... Internals >
namespace_& operator()(Internals&&...internals);
private:
template < typename Class >
void add_(const class_<Class>& internal);
void add_(const data_& internal);
template < typename Enum >
void add_(const enum_<Enum>& internal);
template < typename Function >
void add_(const function_<Function>& internal);
void add_(const namespace_& internal);
void add_(...) = delete;
private:
std::string name_;
class_info_map classes_;
data_info_map datas_;
enum_info_map enums_;
function_info_map functions_;
namespace_info_map namespaces_;
};
}
namespace meta_hpp
{
inline namespace_::namespace_(std::string name)
: name_{std::move(name)} {}
inline namespace_info namespace_::make_info() const {
namespace_info info{name_};
info.state_->classes.insert(classes_.begin(), classes_.end());
info.state_->datas.insert(datas_.begin(), datas_.end());
info.state_->enums.insert(enums_.begin(), enums_.end());
info.state_->functions.insert(functions_.begin(), functions_.end());
info.state_->namespaces.insert(namespaces_.begin(), namespaces_.end());
return info;
}
template < typename... Internals >
namespace_& namespace_::operator()(Internals&&...internals) {
(add_(std::forward<Internals>(internals)), ...);
return *this;
}
}
namespace meta_hpp
{
template < typename Class >
void namespace_::add_(const class_<Class>& internal) {
auto info = internal.make_info();
detail::merge_with(classes_, info.name(), info, &class_info::merge);
}
inline void namespace_::add_(const data_& internal) {
auto info = internal.make_info();
detail::merge_with(datas_, info.name(), info, &data_info::merge);
}
template < typename Enum >
void namespace_::add_(const enum_<Enum>& internal) {
auto info = internal.make_info();
detail::merge_with(enums_, info.name(), info, &enum_info::merge);
}
template < typename Function >
void namespace_::add_(const function_<Function>& internal) {
auto info = internal.make_info();
detail::merge_with(functions_, info.name(), info, &function_info::merge);
}
inline void namespace_::add_(const namespace_& internal) {
auto info = internal.make_info();
detail::merge_with(namespaces_, info.name(), info, &namespace_info::merge);
}
}

View File

@@ -1,84 +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)
******************************************************************************/
#pragma once
#include "meta_fwd.hpp"
#include "meta_types/arithmetic_type.hpp"
#include "meta_types/array_type.hpp"
#include "meta_types/base_type.hpp"
#include "meta_types/class_type.hpp"
#include "meta_types/ctor_type.hpp"
#include "meta_types/enum_type.hpp"
#include "meta_types/function_type.hpp"
#include "meta_types/member_type.hpp"
#include "meta_types/method_type.hpp"
#include "meta_types/pointer_type.hpp"
#include "meta_types/reference_type.hpp"
#include "meta_types/void_type.hpp"
namespace meta_hpp
{
namespace detail
{
template < typename Tuple >
struct multi_get_impl;
template < typename... Ts >
struct multi_get_impl<std::tuple<Ts...>> {
static std::vector<any_type> get() {
return { type_db::get<Ts>()... };
}
};
template < typename T >
auto make_any_type() {
if constexpr ( std::is_arithmetic_v<T> ) {
return arithmetic_type{typename_arg<T>};
}
if constexpr ( std::is_array_v<T> ) {
return array_type{typename_arg<T>};
}
if constexpr ( std::is_class_v<T> ) {
return class_type{typename_arg<T>};
}
if constexpr ( std::is_enum_v<T> ) {
return enum_type{typename_arg<T>};
}
if constexpr ( std::is_pointer_v<T> && std::is_function_v<std::remove_pointer_t<T>> ) {
return function_type{typename_arg<T>};
}
if constexpr ( std::is_member_object_pointer_v<T> ) {
return member_type{typename_arg<T>};
}
if constexpr ( std::is_member_function_pointer_v<T> ) {
return method_type{typename_arg<T>};
}
if constexpr ( std::is_pointer_v<T> && !std::is_function_v<std::remove_pointer_t<T>> ) {
return pointer_type{typename_arg<T>};
}
if constexpr ( std::is_reference_v<T> ) {
return reference_type{typename_arg<T>};
}
if constexpr ( std::is_void_v<T> ) {
return void_type{typename_arg<T>};
}
}
}
template < typename T >
const any_type& type_db::get() {
static const auto raw_type = detail::make_any_type<T>();
static const auto type = any_type{raw_type};
return type;
}
template < typename Tuple >
std::vector<any_type> type_db::multi_get() {
return detail::multi_get_impl<Tuple>::get();
}
}

View File

@@ -1,242 +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)
******************************************************************************/
#pragma once
#include "../meta_fwd.hpp"
namespace meta_hpp
{
class type_id final {
public:
type_id() = default;
type_id(type_id&&) = default;
type_id& operator=(type_id&&) = default;
type_id(const type_id&) = default;
type_id& operator=(const type_id&) = default;
explicit operator bool() const noexcept {
return !!id_;
}
std::size_t hash() const noexcept {
return std::hash<underlying_type>{}(id_);
}
friend bool operator<(type_id l, type_id r) noexcept {
return l.id_ < r.id_;
}
friend bool operator==(type_id l, type_id r) noexcept {
return l.id_ == r.id_;
}
friend bool operator!=(type_id l, type_id r) noexcept {
return l.id_ != r.id_;
}
private:
using underlying_type = std::size_t;
underlying_type id_{0u};
private:
friend class type_base;
template < typename T >
explicit type_id(typename_arg_t<T>) noexcept
: id_{type_to_id<T>()} {}
static underlying_type next() noexcept {
static std::atomic<underlying_type> id{};
return ++id;
}
template < typename T >
static underlying_type type_to_id() noexcept {
static const underlying_type id{next()};
return id;
}
};
}
namespace std
{
template <>
struct hash<meta_hpp::type_id> {
size_t operator()(meta_hpp::type_id id) const noexcept {
return id.hash();
}
};
}
namespace meta_hpp
{
class type_base {
public:
template < typename... Ts >
struct tag {};
public:
type_base() = default;
virtual ~type_base() = default;
type_base(type_base&&) = default;
type_base& operator=(type_base&&) = default;
type_base(const type_base&) = default;
type_base& operator=(const type_base&) = default;
type_id id() const noexcept {
return id_;
}
explicit operator bool() const noexcept {
return !!id_;
}
protected:
template < typename... Ts >
explicit type_base(typename_arg_t<Ts...>)
: id_{typename_arg<tag<Ts...>>} {}
private:
type_id id_;
};
//
inline bool operator<(const type_base& l, const type_base& r) noexcept {
return l.id() < r.id();
}
inline bool operator==(const type_base& l, const type_base& r) noexcept {
return l.id() == r.id();
}
inline bool operator!=(const type_base& l, const type_base& r) noexcept {
return l.id() != r.id();
}
}
namespace meta_hpp
{
class any_type final {
public:
any_type() = default;
any_type(any_type&&) = default;
any_type& operator=(any_type&&) = default;
any_type(const any_type&) = default;
any_type& operator=(const any_type&) = default;
type_id id() const noexcept {
return id_;
}
explicit operator bool() const noexcept {
return !!id_;
}
template < typename T >
std::enable_if_t<std::is_base_of_v<type_base, T>, T> as() const noexcept {
using Tptr = std::add_pointer_t<std::add_const_t<T>>;
return is<T>() ? *std::get<Tptr>(type_) : T{};
}
template < typename T >
std::enable_if_t<std::is_base_of_v<type_base, T>, bool> is() const noexcept {
using Tptr = std::add_pointer_t<std::add_const_t<T>>;
return std::holds_alternative<Tptr>(type_);
}
private:
friend class type_db;
template < typename T
, std::enable_if_t<std::is_base_of_v<type_base, T>, int> = 0 >
explicit any_type(const T& type)
: id_{type.id()}
, type_{std::addressof(type)} {}
private:
type_id id_;
std::variant<
const arithmetic_type*,
const array_type*,
const base_type*,
const class_type*,
const ctor_type*,
const enum_type*,
const function_type*,
const member_type*,
const method_type*,
const pointer_type*,
const reference_type*,
const void_type*> type_;
};
//
inline bool operator<(const any_type& l, const any_type& r) noexcept {
return l.id() < r.id();
}
inline bool operator==(const any_type& l, const any_type& r) noexcept {
return l.id() == r.id();
}
inline bool operator!=(const any_type& l, const any_type& r) noexcept {
return l.id() != r.id();
}
//
inline bool operator<(const type_base& l, const any_type& r) noexcept {
return l.id() < r.id();
}
inline bool operator==(const type_base& l, const any_type& r) noexcept {
return l.id() == r.id();
}
inline bool operator!=(const type_base& l, const any_type& r) noexcept {
return l.id() != r.id();
}
//
inline bool operator<(const any_type& l, const type_base& r) noexcept {
return l.id() < r.id();
}
inline bool operator==(const any_type& l, const type_base& r) noexcept {
return l.id() == r.id();
}
inline bool operator!=(const any_type& l, const type_base& r) noexcept {
return l.id() != r.id();
}
}
namespace std
{
template <>
struct hash<meta_hpp::any_type> {
size_t operator()(const meta_hpp::any_type& type) const noexcept {
return type.id().hash();
}
};
}
namespace meta_hpp
{
class type_db final {
public:
type_db() = delete;
template < typename T >
static const any_type& get();
template < typename Tuple >
static std::vector<any_type> multi_get();
};
}

View File

@@ -1,128 +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)
******************************************************************************/
#pragma once
#include "_types_fwd.hpp"
namespace meta_hpp
{
enum class arithmetic_flags : unsigned {
is_const = 1 << 0,
is_signed = 1 << 1,
is_unsigned = 1 << 2,
is_integral = 1 << 3,
is_floating_point = 1 << 4,
};
ENUM_HPP_OPERATORS_DECL(arithmetic_flags)
class arithmetic_type final : public type_base {
public:
arithmetic_type() = default;
arithmetic_type(arithmetic_type&&) = default;
arithmetic_type& operator=(arithmetic_type&&) = default;
arithmetic_type(const arithmetic_type&) = default;
arithmetic_type& operator=(const arithmetic_type&) = default;
template < typename T >
explicit arithmetic_type(typename_arg_t<T>);
std::size_t size() const noexcept;
any_type raw_type() const noexcept;
bitflags<arithmetic_flags> flags() const noexcept;
bool is_const() const noexcept;
bool is_signed() const noexcept;
bool is_unsigned() const noexcept;
bool is_integral() const noexcept;
bool is_floating_point() const noexcept;
private:
struct state;
std::shared_ptr<state> state_;
};
}
namespace meta_hpp::detail
{
template < typename T >
struct arithmetic_traits {
static_assert(std::is_arithmetic_v<T>);
static constexpr std::size_t size{sizeof(T)};
using raw_type = std::remove_const_t<T>;
static any_type make_raw_type() {
return std::is_same_v<T, raw_type>
? any_type{}
: type_db::get<raw_type>();
}
static bitflags<arithmetic_flags> make_flags() noexcept {
bitflags<arithmetic_flags> flags;
if ( std::is_const_v<T> ) flags.set(arithmetic_flags::is_const);
if ( std::is_signed_v<T> ) flags.set(arithmetic_flags::is_signed);
if ( std::is_unsigned_v<T> ) flags.set(arithmetic_flags::is_unsigned);
if ( std::is_integral_v<T> ) flags.set(arithmetic_flags::is_integral);
if ( std::is_floating_point_v<T> ) flags.set(arithmetic_flags::is_floating_point);
return flags;
}
};
}
namespace meta_hpp
{
struct arithmetic_type::state final {
const std::size_t size;
const any_type raw_type;
const bitflags<arithmetic_flags> flags;
};
template < typename T >
arithmetic_type::arithmetic_type(typename_arg_t<T>)
: type_base{typename_arg<struct arithmetic_type_tag, T>}
, state_{std::make_shared<state>(state{
detail::arithmetic_traits<T>::size,
detail::arithmetic_traits<T>::make_raw_type(),
detail::arithmetic_traits<T>::make_flags(),
})} {
static_assert(std::is_arithmetic_v<T>);
}
inline std::size_t arithmetic_type::size() const noexcept {
return state_->size;
}
inline any_type arithmetic_type::raw_type() const noexcept {
return state_->raw_type;
}
inline bitflags<arithmetic_flags> arithmetic_type::flags() const noexcept {
return state_->flags;
}
inline bool arithmetic_type::is_const() const noexcept {
return state_->flags.has(arithmetic_flags::is_const);
}
inline bool arithmetic_type::is_signed() const noexcept {
return state_->flags.has(arithmetic_flags::is_signed);
}
inline bool arithmetic_type::is_unsigned() const noexcept {
return state_->flags.has(arithmetic_flags::is_unsigned);
}
inline bool arithmetic_type::is_integral() const noexcept {
return state_->flags.has(arithmetic_flags::is_integral);
}
inline bool arithmetic_type::is_floating_point() const noexcept {
return state_->flags.has(arithmetic_flags::is_floating_point);
}
}

View File

@@ -1,108 +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)
******************************************************************************/
#pragma once
#include "_types_fwd.hpp"
namespace meta_hpp
{
enum class array_flags : unsigned {
is_bounded = 1 << 0,
is_unbounded = 1 << 1,
};
ENUM_HPP_OPERATORS_DECL(array_flags)
class array_type final : public type_base {
public:
array_type() = default;
array_type(array_type&&) = default;
array_type& operator=(array_type&&) = default;
array_type(const array_type&) = default;
array_type& operator=(const array_type&) = default;
template < typename T >
explicit array_type(typename_arg_t<T>);
std::size_t extent() const noexcept;
any_type data_type() const noexcept;
bitflags<array_flags> flags() const noexcept;
bool is_bounded() const noexcept;
bool is_unbounded() const noexcept;
private:
struct state;
std::shared_ptr<state> state_;
};
}
namespace meta_hpp
{
struct array_type::state final {
const std::size_t extent;
const any_type data_type;
const bitflags<array_flags> flags;
};
}
namespace meta_hpp::detail
{
template < typename T >
struct array_traits {
static_assert(std::is_array_v<T>);
static constexpr std::size_t extent{std::extent_v<T>};
using data_type = std::remove_extent_t<T>;
static any_type make_data_type() {
return type_db::get<data_type>();
}
static bitflags<array_flags> make_flags() noexcept {
bitflags<array_flags> flags;
if ( stdex::is_bounded_array_v<T> ) flags.set(array_flags::is_bounded);
if ( stdex::is_unbounded_array_v<T> ) flags.set(array_flags::is_unbounded);
return flags;
}
};
}
namespace meta_hpp
{
template < typename T >
array_type::array_type(typename_arg_t<T>)
: type_base{typename_arg<struct array_type_tag, T>}
, state_{std::make_shared<state>(state{
detail::array_traits<T>::extent,
detail::array_traits<T>::make_data_type(),
detail::array_traits<T>::make_flags(),
})} {
static_assert(std::is_array_v<T>);
}
inline std::size_t array_type::extent() const noexcept {
return state_->extent;
}
inline any_type array_type::data_type() const noexcept {
return state_->data_type;
}
inline bitflags<array_flags> array_type::flags() const noexcept {
return state_->flags;
}
inline bool array_type::is_bounded() const noexcept {
return state_->flags.has(array_flags::is_bounded);
}
inline bool array_type::is_unbounded() const noexcept {
return state_->flags.has(array_flags::is_unbounded);
}
}

View File

@@ -1,77 +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)
******************************************************************************/
#pragma once
#include "_types_fwd.hpp"
namespace meta_hpp
{
class base_type final : public type_base {
public:
base_type() = default;
base_type(base_type&&) = default;
base_type& operator=(base_type&&) = default;
base_type(const base_type&) = default;
base_type& operator=(const base_type&) = default;
template < typename Base, typename Derived >
explicit base_type(typename_arg_t<Base>, typename_arg_t<Derived>);
any_type base_class_type() const noexcept;
any_type derived_class_type() const noexcept;
private:
struct state;
std::shared_ptr<state> state_;
};
}
namespace meta_hpp::detail
{
template < typename Base, typename Derived >
struct base_traits {
static_assert(std::is_base_of_v<Base, Derived>);
using base_class_type = Base;
using derived_class_type = Derived;
static any_type make_base_class_type() {
return type_db::get<base_class_type>();
}
static any_type make_derived_class_type() {
return type_db::get<derived_class_type>();
}
};
}
namespace meta_hpp
{
struct base_type::state final {
const any_type base_class_type;
const any_type derived_class_type;
};
template < typename Base, typename Derived >
base_type::base_type(typename_arg_t<Base>, typename_arg_t<Derived>)
: type_base{typename_arg<struct base_type_tag, Base, Derived>}
, state_{std::make_shared<state>(state{
detail::base_traits<Base, Derived>::make_base_class_type(),
detail::base_traits<Base, Derived>::make_derived_class_type(),
})} {
static_assert(std::is_base_of_v<Base, Derived>);
}
inline any_type base_type::base_class_type() const noexcept {
return state_->base_class_type;
}
inline any_type base_type::derived_class_type() const noexcept {
return state_->derived_class_type;
}
}

View File

@@ -1,128 +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)
******************************************************************************/
#pragma once
#include "_types_fwd.hpp"
namespace meta_hpp
{
enum class class_flags : unsigned {
is_const = 1 << 0,
is_empty = 1 << 1,
is_final = 1 << 2,
is_abstract = 1 << 3,
is_polymorphic = 1 << 4,
};
ENUM_HPP_OPERATORS_DECL(class_flags)
class class_type final : public type_base {
public:
class_type() = default;
class_type(class_type&&) = default;
class_type& operator=(class_type&&) = default;
class_type(const class_type&) = default;
class_type& operator=(const class_type&) = default;
template < typename T >
explicit class_type(typename_arg_t<T>);
std::size_t size() const noexcept;
any_type raw_type() const noexcept;
bitflags<class_flags> flags() const noexcept;
bool is_const() const noexcept;
bool is_empty() const noexcept;
bool is_final() const noexcept;
bool is_abstract() const noexcept;
bool is_polymorphic() const noexcept;
private:
struct state;
std::shared_ptr<state> state_;
};
}
namespace meta_hpp::detail
{
template < typename T >
struct class_traits {
static_assert(std::is_class_v<T>);
static constexpr std::size_t size{sizeof(T)};
using raw_type = std::remove_const_t<T>;
static any_type make_raw_type() {
return std::is_same_v<T, raw_type>
? any_type{}
: type_db::get<raw_type>();
}
static bitflags<class_flags> make_flags() noexcept {
bitflags<class_flags> flags;
if ( std::is_const_v<T> ) flags.set(class_flags::is_const);
if ( std::is_empty_v<T> ) flags.set(class_flags::is_empty);
if ( std::is_final_v<T> ) flags.set(class_flags::is_final);
if ( std::is_abstract_v<T> ) flags.set(class_flags::is_abstract);
if ( std::is_polymorphic_v<T> ) flags.set(class_flags::is_polymorphic);
return flags;
}
};
}
namespace meta_hpp
{
struct class_type::state final {
const std::size_t size;
const any_type raw_type;
const bitflags<class_flags> flags;
};
template < typename T >
class_type::class_type(typename_arg_t<T>)
: type_base{typename_arg<struct class_type_tag, T>}
, state_{std::make_shared<state>(state{
detail::class_traits<T>::size,
detail::class_traits<T>::make_raw_type(),
detail::class_traits<T>::make_flags(),
})} {
static_assert(std::is_class_v<T>);
}
inline std::size_t class_type::size() const noexcept {
return state_->size;
}
inline any_type class_type::raw_type() const noexcept {
return state_->raw_type;
}
inline bitflags<class_flags> class_type::flags() const noexcept {
return state_->flags;
}
inline bool class_type::is_const() const noexcept {
return state_->flags.has(class_flags::is_const);
}
inline bool class_type::is_empty() const noexcept {
return state_->flags.has(class_flags::is_empty);
}
inline bool class_type::is_final() const noexcept {
return state_->flags.has(class_flags::is_final);
}
inline bool class_type::is_abstract() const noexcept {
return state_->flags.has(class_flags::is_abstract);
}
inline bool class_type::is_polymorphic() const noexcept {
return state_->flags.has(class_flags::is_polymorphic);
}
}

View File

@@ -1,118 +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)
******************************************************************************/
#pragma once
#include "_types_fwd.hpp"
namespace meta_hpp
{
enum class ctor_flags : unsigned {
is_noexcept = 1 << 0,
};
ENUM_HPP_OPERATORS_DECL(ctor_flags)
class ctor_type final : public type_base {
public:
ctor_type() = default;
ctor_type(ctor_type&&) = default;
ctor_type& operator=(ctor_type&&) = default;
ctor_type(const ctor_type&) = default;
ctor_type& operator=(const ctor_type&) = default;
template < typename Class, typename... Args >
explicit ctor_type(typename_arg_t<Class>, typename_arg_t<Args...>);
std::size_t arity() const noexcept;
any_type class_type() const noexcept;
any_type argument_type(std::size_t i) const noexcept;
const std::vector<any_type>& argument_types() const noexcept;
bitflags<ctor_flags> flags() const noexcept;
bool is_noexcept() const noexcept;
private:
struct state;
std::shared_ptr<state> state_;
};
}
namespace meta_hpp::detail
{
template < typename Class, typename... Args >
struct ctor_traits {
static_assert(std::is_constructible_v<Class, Args...>);
static constexpr std::size_t arity{sizeof...(Args)};
using class_type = Class;
using argument_types = std::tuple<Args...>;
static any_type make_class_type() {
return type_db::get<class_type>();
}
static std::vector<any_type> make_argument_types() {
return type_db::multi_get<argument_types>();
}
static bitflags<ctor_flags> make_flags() noexcept {
bitflags<ctor_flags> flags;
if ( std::is_nothrow_constructible_v<Class, Args...> ) flags.set(ctor_flags::is_noexcept);
return flags;
}
};
}
namespace meta_hpp
{
struct ctor_type::state final {
const std::size_t arity;
const any_type class_type;
const std::vector<any_type> argument_types;
const bitflags<ctor_flags> flags;
};
template < typename Class, typename... Args >
ctor_type::ctor_type(typename_arg_t<Class>, typename_arg_t<Args...>)
: type_base{typename_arg<struct ctor_type_tag, Class, Args...>}
, state_{std::make_shared<state>(state{
detail::ctor_traits<Class, Args...>::arity,
detail::ctor_traits<Class, Args...>::make_class_type(),
detail::ctor_traits<Class, Args...>::make_argument_types(),
detail::ctor_traits<Class, Args...>::make_flags(),
})} {
static_assert(std::is_class_v<Class>);
static_assert(std::is_constructible_v<Class, Args...>);
}
inline std::size_t ctor_type::arity() const noexcept {
return state_->arity;
}
inline any_type ctor_type::class_type() const noexcept {
return state_->class_type;
}
inline any_type ctor_type::argument_type(std::size_t i) const noexcept {
return i < state_->argument_types.size()
? state_->argument_types[i]
: any_type{};
}
inline const std::vector<any_type>& ctor_type::argument_types() const noexcept {
return state_->argument_types;
}
inline bitflags<ctor_flags> ctor_type::flags() const noexcept {
return state_->flags;
}
inline bool ctor_type::is_noexcept() const noexcept {
return state_->flags.has(ctor_flags::is_noexcept);
}
}

View File

@@ -1,112 +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)
******************************************************************************/
#pragma once
#include "_types_fwd.hpp"
namespace meta_hpp
{
enum class enum_flags : unsigned {
is_const = 1 << 0,
};
ENUM_HPP_OPERATORS_DECL(enum_flags)
class enum_type final : public type_base {
public:
enum_type() = default;
enum_type(enum_type&&) = default;
enum_type& operator=(enum_type&&) = default;
enum_type(const enum_type&) = default;
enum_type& operator=(const enum_type&) = default;
template < typename T >
explicit enum_type(typename_arg_t<T>);
std::size_t size() const noexcept;
any_type raw_type() const noexcept;
any_type underlying_type() const noexcept;
bitflags<enum_flags> flags() const noexcept;
bool is_const() const noexcept;
private:
struct state;
std::shared_ptr<state> state_;
};
}
namespace meta_hpp::detail
{
template < typename T >
struct enum_traits {
static_assert(std::is_enum_v<T>);
static constexpr std::size_t size{sizeof(T)};
using raw_type = std::remove_const_t<T>;
using underlying_type = std::underlying_type_t<T>;
static any_type make_raw_type() {
return std::is_same_v<T, raw_type>
? any_type{}
: type_db::get<raw_type>();
}
static any_type make_underlying_type() {
return type_db::get<underlying_type>();
}
static bitflags<enum_flags> make_flags() noexcept {
bitflags<enum_flags> flags;
if ( std::is_const_v<T> ) flags.set(enum_flags::is_const);
return flags;
}
};
}
namespace meta_hpp
{
struct enum_type::state final {
const std::size_t size;
const any_type raw_type;
const any_type underlying_type;
const bitflags<enum_flags> flags;
};
template < typename T >
enum_type::enum_type(typename_arg_t<T>)
: type_base{typename_arg<struct enum_type_tag, T>}
, state_{std::make_shared<state>(state{
detail::enum_traits<T>::size,
detail::enum_traits<T>::make_raw_type(),
detail::enum_traits<T>::make_underlying_type(),
detail::enum_traits<T>::make_flags(),
})} {
static_assert(std::is_enum_v<T>);
}
inline std::size_t enum_type::size() const noexcept {
return state_->size;
}
inline any_type enum_type::raw_type() const noexcept {
return state_->raw_type;
}
inline any_type enum_type::underlying_type() const noexcept {
return state_->underlying_type;
}
inline bitflags<enum_flags> enum_type::flags() const noexcept {
return state_->flags;
}
inline bool enum_type::is_const() const noexcept {
return state_->flags.has(enum_flags::is_const);
}
}

View File

@@ -1,125 +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)
******************************************************************************/
#pragma once
#include "_types_fwd.hpp"
namespace meta_hpp
{
enum class function_flags : unsigned {
is_noexcept = 1 << 0,
};
ENUM_HPP_OPERATORS_DECL(function_flags)
class function_type final : public type_base {
public:
function_type() = default;
function_type(function_type&&) = default;
function_type& operator=(function_type&&) = default;
function_type(const function_type&) = default;
function_type& operator=(const function_type&) = default;
template < typename T >
explicit function_type(typename_arg_t<T>);
std::size_t arity() const noexcept;
any_type return_type() const noexcept;
any_type argument_type(std::size_t i) const noexcept;
const std::vector<any_type>& argument_types() const noexcept;
bitflags<function_flags> flags() const noexcept;
bool is_noexcept() const noexcept;
private:
struct state;
std::shared_ptr<state> state_;
};
}
namespace meta_hpp::detail
{
template < typename T >
struct function_pointer_traits;
template < typename R, typename... Args >
struct function_pointer_traits<R(*)(Args...)> {
static constexpr std::size_t arity{sizeof...(Args)};
using return_type = R;
using argument_types = std::tuple<Args...>;
static any_type make_return_type() {
return type_db::get<return_type>();
}
static std::vector<any_type> make_argument_types() {
return type_db::multi_get<argument_types>();
}
static bitflags<function_flags> make_flags() noexcept {
return bitflags<function_flags>{};
}
};
template < typename R, typename... Args >
struct function_pointer_traits<R(*)(Args...) noexcept> : function_pointer_traits<R(*)(Args...)> {
static bitflags<function_flags> make_flags() noexcept {
return function_flags::is_noexcept;
}
};
}
namespace meta_hpp
{
struct function_type::state final {
const std::size_t arity;
const any_type return_type;
const std::vector<any_type> argument_types;
const bitflags<function_flags> flags;
};
template < typename T >
function_type::function_type(typename_arg_t<T>)
: type_base{typename_arg<struct function_type_tag, T>}
, state_{std::make_shared<state>(state{
detail::function_pointer_traits<T>::arity,
detail::function_pointer_traits<T>::make_return_type(),
detail::function_pointer_traits<T>::make_argument_types(),
detail::function_pointer_traits<T>::make_flags(),
})} {
static_assert(std::is_pointer_v<T>);
static_assert(std::is_function_v<std::remove_pointer_t<T>>);
}
inline std::size_t function_type::arity() const noexcept {
return state_->arity;
}
inline any_type function_type::return_type() const noexcept {
return state_->return_type;
}
inline any_type function_type::argument_type(std::size_t i) const noexcept {
return i < state_->argument_types.size()
? state_->argument_types[i]
: any_type{};
}
inline const std::vector<any_type>& function_type::argument_types() const noexcept {
return state_->argument_types;
}
inline bitflags<function_flags> function_type::flags() const noexcept {
return state_->flags;
}
inline bool function_type::is_noexcept() const noexcept {
return state_->flags.has(function_flags::is_noexcept);
}
}

View File

@@ -1,81 +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)
******************************************************************************/
#pragma once
#include "_types_fwd.hpp"
namespace meta_hpp
{
class member_type final : public type_base {
public:
member_type() = default;
member_type(member_type&&) = default;
member_type& operator=(member_type&&) = default;
member_type(const member_type&) = default;
member_type& operator=(const member_type&) = default;
template < typename T >
explicit member_type(typename_arg_t<T>);
any_type class_type() const noexcept;
any_type value_type() const noexcept;
private:
struct state;
std::shared_ptr<state> state_;
};
}
namespace meta_hpp
{
struct member_type::state final {
const any_type class_type;
const any_type value_type;
};
}
namespace meta_hpp::detail
{
template < typename T >
struct member_pointer_traits;
template < typename V, typename C >
struct member_pointer_traits<V C::*> {
using class_type = C;
using value_type = V;
static any_type make_class_type() {
return type_db::get<class_type>();
}
static any_type make_value_type() {
return type_db::get<value_type>();
}
};
}
namespace meta_hpp
{
template < typename T >
member_type::member_type(typename_arg_t<T>)
: type_base{typename_arg<struct member_type_tag, T>}
, state_{std::make_shared<state>(state{
detail::member_pointer_traits<T>::make_class_type(),
detail::member_pointer_traits<T>::make_value_type(),
})} {
static_assert(std::is_member_object_pointer_v<T>);
}
inline any_type member_type::class_type() const noexcept {
return state_->class_type;
}
inline any_type member_type::value_type() const noexcept {
return state_->value_type;
}
}

View File

@@ -1,340 +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)
******************************************************************************/
#pragma once
#include "_types_fwd.hpp"
namespace meta_hpp
{
enum class method_flags : unsigned {
is_const = 1 << 0,
is_noexcept = 1 << 1,
is_volatile = 1 << 2,
is_lvalue_qualified = 1 << 3,
is_rvalue_qualified = 1 << 4,
};
ENUM_HPP_OPERATORS_DECL(method_flags)
class method_type final : public type_base {
public:
method_type() = default;
method_type(method_type&&) = default;
method_type& operator=(method_type&&) = default;
method_type(const method_type&) = default;
method_type& operator=(const method_type&) = default;
template < typename T >
explicit method_type(typename_arg_t<T>);
std::size_t arity() const noexcept;
any_type class_type() const noexcept;
any_type return_type() const noexcept;
any_type argument_type(std::size_t i) const noexcept;
const std::vector<any_type>& argument_types() const noexcept;
bitflags<method_flags> flags() const noexcept;
bool is_const() const noexcept;
bool is_noexcept() const noexcept;
bool is_volatile() const noexcept;
bool is_lvalue_qualified() const noexcept;
bool is_rvalue_qualified() const noexcept;
private:
struct state;
std::shared_ptr<state> state_;
};
}
namespace meta_hpp::detail
{
template < typename T >
struct method_pointer_traits;
template < typename R, typename C, typename... Args >
struct method_pointer_traits<R(C::*)(Args...)> {
static constexpr std::size_t arity{sizeof...(Args)};
using class_type = C;
using return_type = R;
using qualified_type = C;
using argument_types = std::tuple<Args...>;
static any_type make_class_type() {
return type_db::get<class_type>();
}
static any_type make_return_type() {
return type_db::get<return_type>();
}
static std::vector<any_type> make_argument_types() {
return type_db::multi_get<argument_types>();
}
static bitflags<method_flags> make_flags() noexcept {
return bitflags<method_flags>{};
}
};
template < typename R, typename C, typename... Args >
struct method_pointer_traits<R(C::*)(Args...) const> : method_pointer_traits<R(C::*)(Args...)> {
using qualified_type = const C;
static bitflags<method_flags> make_flags() noexcept {
return method_flags::is_const;
}
};
template < typename R, typename C, typename... Args >
struct method_pointer_traits<R(C::*)(Args...) noexcept> : method_pointer_traits<R(C::*)(Args...)> {
using qualified_type = C;
static bitflags<method_flags> make_flags() noexcept {
return method_flags::is_noexcept;
}
};
template < typename R, typename C, typename... Args >
struct method_pointer_traits<R(C::*)(Args...) const noexcept> : method_pointer_traits<R(C::*)(Args...)> {
using qualified_type = const C;
static bitflags<method_flags> make_flags() noexcept {
return method_flags::is_const | method_flags::is_noexcept;
}
};
template < typename R, typename C, typename... Args >
struct method_pointer_traits<R(C::*)(Args...) &> : method_pointer_traits<R(C::*)(Args...)> {
using qualified_type = C&;
static bitflags<method_flags> make_flags() noexcept {
return method_flags::is_lvalue_qualified;
}
};
template < typename R, typename C, typename... Args >
struct method_pointer_traits<R(C::*)(Args...) & noexcept> : method_pointer_traits<R(C::*)(Args...)> {
using qualified_type = C&;
static bitflags<method_flags> make_flags() noexcept {
return method_flags::is_noexcept | method_flags::is_lvalue_qualified;
}
};
template < typename R, typename C, typename... Args >
struct method_pointer_traits<R(C::*)(Args...) const &> : method_pointer_traits<R(C::*)(Args...)> {
using qualified_type = const C&;
static bitflags<method_flags> make_flags() noexcept {
return method_flags::is_const | method_flags::is_lvalue_qualified;
}
};
template < typename R, typename C, typename... Args >
struct method_pointer_traits<R(C::*)(Args...) const & noexcept> : method_pointer_traits<R(C::*)(Args...)> {
using qualified_type = const C&;
static bitflags<method_flags> make_flags() noexcept {
return method_flags::is_const | method_flags::is_noexcept | method_flags::is_lvalue_qualified;
}
};
template < typename R, typename C, typename... Args >
struct method_pointer_traits<R(C::*)(Args...) &&> : method_pointer_traits<R(C::*)(Args...)> {
using qualified_type = C&&;
static bitflags<method_flags> make_flags() noexcept {
return method_flags::is_rvalue_qualified;
}
};
template < typename R, typename C, typename... Args >
struct method_pointer_traits<R(C::*)(Args...) && noexcept> : method_pointer_traits<R(C::*)(Args...)> {
using qualified_type = C&&;
static bitflags<method_flags> make_flags() noexcept {
return method_flags::is_noexcept | method_flags::is_rvalue_qualified;
}
};
template < typename R, typename C, typename... Args >
struct method_pointer_traits<R(C::*)(Args...) const &&> : method_pointer_traits<R(C::*)(Args...)> {
using qualified_type = const C&&;
static bitflags<method_flags> make_flags() noexcept {
return method_flags::is_const | method_flags::is_rvalue_qualified;
}
};
template < typename R, typename C, typename... Args >
struct method_pointer_traits<R(C::*)(Args...) const && noexcept> : method_pointer_traits<R(C::*)(Args...)> {
using qualified_type = const C&&;
static bitflags<method_flags> make_flags() noexcept {
return method_flags::is_const | method_flags::is_noexcept | method_flags::is_rvalue_qualified;
}
};
//
template < typename R, typename C, typename... Args >
struct method_pointer_traits<R(C::*)(Args...) volatile> : method_pointer_traits<R(C::*)(Args...)> {
using qualified_type = C;
static bitflags<method_flags> make_flags() noexcept {
return method_flags::is_volatile;
}
};
template < typename R, typename C, typename... Args >
struct method_pointer_traits<R(C::*)(Args...) volatile const> : method_pointer_traits<R(C::*)(Args...)> {
using qualified_type = const C;
static bitflags<method_flags> make_flags() noexcept {
return method_flags::is_volatile | method_flags::is_const;
}
};
template < typename R, typename C, typename... Args >
struct method_pointer_traits<R(C::*)(Args...) volatile noexcept> : method_pointer_traits<R(C::*)(Args...)> {
using qualified_type = C;
static bitflags<method_flags> make_flags() noexcept {
return method_flags::is_volatile | method_flags::is_noexcept;
}
};
template < typename R, typename C, typename... Args >
struct method_pointer_traits<R(C::*)(Args...) volatile const noexcept> : method_pointer_traits<R(C::*)(Args...)> {
using qualified_type = const C;
static bitflags<method_flags> make_flags() noexcept {
return method_flags::is_volatile | method_flags::is_const | method_flags::is_noexcept;
}
};
template < typename R, typename C, typename... Args >
struct method_pointer_traits<R(C::*)(Args...) volatile &> : method_pointer_traits<R(C::*)(Args...)> {
using qualified_type = C&;
static bitflags<method_flags> make_flags() noexcept {
return method_flags::is_volatile | method_flags::is_lvalue_qualified;
}
};
template < typename R, typename C, typename... Args >
struct method_pointer_traits<R(C::*)(Args...) volatile & noexcept> : method_pointer_traits<R(C::*)(Args...)> {
using qualified_type = C&;
static bitflags<method_flags> make_flags() noexcept {
return method_flags::is_volatile | method_flags::is_noexcept | method_flags::is_lvalue_qualified;
}
};
template < typename R, typename C, typename... Args >
struct method_pointer_traits<R(C::*)(Args...) volatile const &> : method_pointer_traits<R(C::*)(Args...)> {
using qualified_type = const C&;
static bitflags<method_flags> make_flags() noexcept {
return method_flags::is_volatile | method_flags::is_const | method_flags::is_lvalue_qualified;
}
};
template < typename R, typename C, typename... Args >
struct method_pointer_traits<R(C::*)(Args...) volatile const & noexcept> : method_pointer_traits<R(C::*)(Args...)> {
using qualified_type = const C&;
static bitflags<method_flags> make_flags() noexcept {
return method_flags::is_volatile | method_flags::is_const | method_flags::is_noexcept | method_flags::is_lvalue_qualified;
}
};
template < typename R, typename C, typename... Args >
struct method_pointer_traits<R(C::*)(Args...) volatile &&> : method_pointer_traits<R(C::*)(Args...)> {
using qualified_type = C&&;
static bitflags<method_flags> make_flags() noexcept {
return method_flags::is_volatile | method_flags::is_rvalue_qualified;
}
};
template < typename R, typename C, typename... Args >
struct method_pointer_traits<R(C::*)(Args...) volatile && noexcept> : method_pointer_traits<R(C::*)(Args...)> {
using qualified_type = C&&;
static bitflags<method_flags> make_flags() noexcept {
return method_flags::is_volatile | method_flags::is_noexcept | method_flags::is_rvalue_qualified;
}
};
template < typename R, typename C, typename... Args >
struct method_pointer_traits<R(C::*)(Args...) volatile const &&> : method_pointer_traits<R(C::*)(Args...)> {
using qualified_type = const C&&;
static bitflags<method_flags> make_flags() noexcept {
return method_flags::is_volatile | method_flags::is_const | method_flags::is_rvalue_qualified;
}
};
template < typename R, typename C, typename... Args >
struct method_pointer_traits<R(C::*)(Args...) volatile const && noexcept> : method_pointer_traits<R(C::*)(Args...)> {
using qualified_type = const C&&;
static bitflags<method_flags> make_flags() noexcept {
return method_flags::is_volatile | method_flags::is_const | method_flags::is_noexcept | method_flags::is_rvalue_qualified;
}
};
}
namespace meta_hpp
{
struct method_type::state final {
const std::size_t arity;
const any_type class_type;
const any_type return_type;
const std::vector<any_type> argument_types;
const bitflags<method_flags> flags;
};
template < typename T >
method_type::method_type(typename_arg_t<T>)
: type_base{typename_arg<struct member_type_tag, T>}
, state_{std::make_shared<state>(state{
detail::method_pointer_traits<T>::arity,
detail::method_pointer_traits<T>::make_class_type(),
detail::method_pointer_traits<T>::make_return_type(),
detail::method_pointer_traits<T>::make_argument_types(),
detail::method_pointer_traits<T>::make_flags(),
})} {
static_assert(std::is_member_function_pointer_v<T>);
}
inline std::size_t method_type::arity() const noexcept {
return state_->arity;
}
inline any_type method_type::class_type() const noexcept {
return state_->class_type;
}
inline any_type method_type::return_type() const noexcept {
return state_->return_type;
}
inline any_type method_type::argument_type(std::size_t i) const noexcept {
return i < state_->argument_types.size()
? state_->argument_types[i]
: any_type{};
}
inline const std::vector<any_type>& method_type::argument_types() const noexcept {
return state_->argument_types;
}
inline bitflags<method_flags> method_type::flags() const noexcept {
return state_->flags;
}
inline bool method_type::is_const() const noexcept {
return state_->flags.has(method_flags::is_const);
}
inline bool method_type::is_noexcept() const noexcept {
return state_->flags.has(method_flags::is_noexcept);
}
inline bool method_type::is_volatile() const noexcept {
return state_->flags.has(method_flags::is_volatile);
}
inline bool method_type::is_lvalue_qualified() const noexcept {
return state_->flags.has(method_flags::is_lvalue_qualified);
}
inline bool method_type::is_rvalue_qualified() const noexcept {
return state_->flags.has(method_flags::is_rvalue_qualified);
}
}

View File

@@ -1,88 +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)
******************************************************************************/
#pragma once
#include "_types_fwd.hpp"
namespace meta_hpp
{
enum class pointer_flags : unsigned {
is_const = 1 << 0,
};
class pointer_type final : public type_base {
public:
pointer_type() = default;
pointer_type(pointer_type&&) = default;
pointer_type& operator=(pointer_type&&) = default;
pointer_type(const pointer_type&) = default;
pointer_type& operator=(const pointer_type&) = default;
template < typename T >
explicit pointer_type(typename_arg_t<T>);
any_type data_type() const noexcept;
bitflags<pointer_flags> flags() const noexcept;
bool is_const() const noexcept;
private:
struct state;
std::shared_ptr<state> state_;
};
}
namespace meta_hpp::detail
{
template < typename T >
struct pointer_traits {
static_assert(std::is_pointer_v<T>);
using data_type = std::remove_pointer_t<T>;
static any_type make_data_type() {
return type_db::get<data_type>();
}
static bitflags<pointer_flags> make_flags() noexcept {
bitflags<pointer_flags> flags;
if ( std::is_const_v<T> ) flags.set(pointer_flags::is_const);
return flags;
}
};
}
namespace meta_hpp
{
struct pointer_type::state final {
const any_type data_type;
const bitflags<pointer_flags> flags;
};
template < typename T >
pointer_type::pointer_type(typename_arg_t<T>)
: type_base{typename_arg<struct pointer_type_tag, T>}
, state_{std::make_shared<state>(state{
detail::pointer_traits<T>::make_data_type(),
detail::pointer_traits<T>::make_flags(),
})} {
static_assert(std::is_pointer_v<T>);
static_assert(!std::is_function_v<std::remove_pointer_t<T>>);
}
inline any_type pointer_type::data_type() const noexcept {
return state_->data_type;
}
inline bitflags<pointer_flags> pointer_type::flags() const noexcept {
return state_->flags;
}
inline bool pointer_type::is_const() const noexcept {
return state_->flags.has(pointer_flags::is_const);
}
}

View File

@@ -1,96 +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)
******************************************************************************/
#pragma once
#include "_types_fwd.hpp"
namespace meta_hpp
{
enum class reference_flags : unsigned {
is_lvalue = 1 << 0,
is_rvalue = 1 << 1,
};
ENUM_HPP_OPERATORS_DECL(reference_flags)
class reference_type final : public type_base {
public:
reference_type() = default;
reference_type(reference_type&&) = default;
reference_type& operator=(reference_type&&) = default;
reference_type(const reference_type&) = default;
reference_type& operator=(const reference_type&) = default;
template < typename T >
explicit reference_type(typename_arg_t<T>);
any_type data_type() const noexcept;
bitflags<reference_flags> flags() const noexcept;
bool is_lvalue() const noexcept;
bool is_rvalue() const noexcept;
private:
struct state;
std::shared_ptr<state> state_;
};
}
namespace meta_hpp::detail
{
template < typename T >
struct reference_traits {
static_assert(std::is_reference_v<T>);
using data_type = std::remove_reference_t<T>;
static any_type make_data_type() {
return type_db::get<data_type>();
}
static bitflags<reference_flags> make_flags() noexcept {
bitflags<reference_flags> flags;
if ( std::is_lvalue_reference_v<T> ) flags.set(reference_flags::is_lvalue);
if ( std::is_rvalue_reference_v<T> ) flags.set(reference_flags::is_rvalue);
return flags;
}
};
}
namespace meta_hpp
{
struct reference_type::state final {
const any_type data_type;
const bitflags<reference_flags> flags;
};
template < typename T >
reference_type::reference_type(typename_arg_t<T>)
: type_base{typename_arg<struct reference_type_tag, T>}
, state_{std::make_shared<state>(state{
detail::reference_traits<T>::make_data_type(),
detail::reference_traits<T>::make_flags(),
})} {
static_assert(std::is_reference_v<T>);
}
inline any_type reference_type::data_type() const noexcept {
return state_->data_type;
}
inline bitflags<reference_flags> reference_type::flags() const noexcept {
return state_->flags;
}
inline bool reference_type::is_lvalue() const noexcept {
return state_->flags.has(reference_flags::is_lvalue);
}
inline bool reference_type::is_rvalue() const noexcept {
return state_->flags.has(reference_flags::is_rvalue);
}
}

View File

@@ -1,94 +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)
******************************************************************************/
#pragma once
#include "_types_fwd.hpp"
namespace meta_hpp
{
enum class void_flags : unsigned {
is_const = 1 << 0,
};
ENUM_HPP_OPERATORS_DECL(void_flags)
class void_type final : public type_base {
public:
void_type() = default;
void_type(void_type&&) = default;
void_type& operator=(void_type&&) = default;
void_type(const void_type&) = default;
void_type& operator=(const void_type&) = default;
template < typename T >
explicit void_type(typename_arg_t<T>);
any_type raw_type() const noexcept;
bitflags<void_flags> flags() const noexcept;
bool is_const() const noexcept;
private:
struct state;
std::shared_ptr<state> state_;
};
}
namespace meta_hpp
{
struct void_type::state final {
const any_type raw_type;
const bitflags<void_flags> flags;
};
}
namespace meta_hpp::detail
{
template < typename T >
struct void_traits {
static_assert(std::is_void_v<T>);
using raw_type = std::remove_const_t<T>;
static any_type make_raw_type() {
return std::is_same_v<T, raw_type>
? any_type{}
: type_db::get<raw_type>();
}
static bitflags<void_flags> make_flags() noexcept {
bitflags<void_flags> flags;
if ( std::is_const_v<T> ) flags.set(void_flags::is_const);
return flags;
}
};
}
namespace meta_hpp
{
template < typename T >
void_type::void_type(typename_arg_t<T>)
: type_base{typename_arg<struct void_type_tag, T>}
, state_{std::make_shared<state>(state{
detail::void_traits<T>::make_raw_type(),
detail::void_traits<T>::make_flags(),
})} {
static_assert(std::is_void_v<T>);
}
inline any_type void_type::raw_type() const noexcept {
return state_->raw_type;
}
inline bitflags<void_flags> void_type::flags() const noexcept {
return state_->flags;
}
inline bool void_type::is_const() const noexcept {
return state_->flags.has(void_flags::is_const);
}
}

View File

@@ -1,13 +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)
******************************************************************************/
#pragma once
#include "meta_fwd.hpp"
#include "meta_utilities/arg.hpp"
#include "meta_utilities/inst.hpp"
#include "meta_utilities/value.hpp"

View File

@@ -1,9 +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)
******************************************************************************/
#pragma once
#include "../meta_fwd.hpp"

View File

@@ -1,286 +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)
******************************************************************************/
#pragma once
#include "../meta_fwd.hpp"
#include "value.hpp"
namespace meta_hpp
{
class arg_base {
public:
enum class ref_types {
ref,
rref,
cref,
crref,
};
public:
arg_base() = delete;
arg_base(arg_base&&) = delete;
arg_base& operator=(arg_base&&) = delete;
arg_base(const arg_base&) = delete;
arg_base& operator=(const arg_base&) = delete;
template < typename T, std::enable_if_t<
std::is_pointer_v<T> || std::is_lvalue_reference_v<T>
, int> = 0 >
explicit arg_base(typename_arg_t<T>);
template < typename T, std::enable_if_t<
std::is_rvalue_reference_v<T> ||
(!std::is_pointer_v<T> && !std::is_reference_v<T>)
, int> = 0 >
explicit arg_base(typename_arg_t<T>);
explicit arg_base(value& v);
explicit arg_base(value&& v);
explicit arg_base(const value& v);
explicit arg_base(const value&& v);
bool is_const() const noexcept;
bool is_lvalue() const noexcept;
bool is_rvalue() const noexcept;
any_type raw_type() const noexcept;
ref_types ref_type() const noexcept;
template < typename To >
bool can_cast_to() const noexcept;
private:
any_type raw_type_{};
ref_types ref_type_{};
};
}
namespace meta_hpp
{
template < typename T, std::enable_if_t<
std::is_pointer_v<T> || std::is_lvalue_reference_v<T>
, int> >
arg_base::arg_base(typename_arg_t<T>)
: raw_type_{type_db::get<stdex::remove_cvref_t<T>>()}
, ref_type_{std::is_const_v<std::remove_reference_t<T>> ? ref_types::cref : ref_types::ref} {}
template < typename T, std::enable_if_t<
std::is_rvalue_reference_v<T> ||
(!std::is_pointer_v<T> && !std::is_reference_v<T>)
, int> >
arg_base::arg_base(typename_arg_t<T>)
: raw_type_{type_db::get<stdex::remove_cvref_t<T>>()}
, ref_type_{std::is_const_v<std::remove_reference_t<T>> ? ref_types::crref : ref_types::rref} {}
inline arg_base::arg_base(value& v)
: raw_type_{v.type()}
, ref_type_{ref_types::ref} {}
inline arg_base::arg_base(value&& v)
: raw_type_{v.type()}
, ref_type_{ref_types::rref} {}
inline arg_base::arg_base(const value& v)
: raw_type_{v.type()}
, ref_type_{ref_types::cref} {}
inline arg_base::arg_base(const value&& v)
: raw_type_{v.type()}
, ref_type_{ref_types::crref} {}
inline bool arg_base::is_const() const noexcept {
return ref_type_ == ref_types::cref
|| ref_type_ == ref_types::crref;
}
inline bool arg_base::is_lvalue() const noexcept {
return ref_type_ == ref_types::ref
|| ref_type_ == ref_types::cref;
}
inline bool arg_base::is_rvalue() const noexcept {
return ref_type_ == ref_types::rref
|| ref_type_ == ref_types::crref;
}
inline any_type arg_base::raw_type() const noexcept {
return raw_type_;
}
inline arg_base::ref_types arg_base::ref_type() const noexcept {
return ref_type_;
}
template < typename To >
bool arg_base::can_cast_to() const noexcept {
if constexpr ( std::is_pointer_v<To> ) {
using to_raw_type = std::remove_cv_t<To>;
using to_raw_ptr_type = std::remove_cv_t<std::remove_pointer_t<to_raw_type>>;
return raw_type() == type_db::get<to_raw_type>()
|| raw_type() == type_db::get<to_raw_ptr_type*>();
}
if constexpr ( std::is_reference_v<To> ) {
constexpr bool to_const = std::is_const_v<std::remove_reference_t<To>>;
if constexpr ( !to_const ) {
if ( is_const() ) {
return false;
}
}
if constexpr ( std::is_lvalue_reference_v<To> ) {
if constexpr ( !to_const ) {
if ( is_rvalue() ) {
return false;
}
}
}
if constexpr ( std::is_rvalue_reference_v<To> ) {
if ( !is_rvalue() ) {
return false;
}
}
using to_raw_type = stdex::remove_cvref_t<To>;
if ( raw_type() == type_db::get<to_raw_type>() ) {
return true;
}
if constexpr ( to_const && std::is_pointer_v<to_raw_type> ) {
using to_raw_ptr_type = std::remove_cv_t<std::remove_pointer_t<to_raw_type>>;
return raw_type() == type_db::get<to_raw_ptr_type*>();
}
return false;
}
if constexpr ( !std::is_pointer_v<To> && !std::is_reference_v<To> ) {
using to_raw_type = std::remove_cv_t<To>;
if ( raw_type() != type_db::get<to_raw_type>() ) {
return false;
}
return (ref_type() == ref_types::ref && std::is_constructible_v<To, to_raw_type&>)
|| (ref_type() == ref_types::cref && std::is_constructible_v<To, const to_raw_type&>)
|| (ref_type() == ref_types::rref && std::is_constructible_v<To, to_raw_type&&>)
|| (ref_type() == ref_types::crref && std::is_constructible_v<To, const to_raw_type&&>);
}
}
}
namespace meta_hpp
{
class arg final : public arg_base {
public:
arg() = delete;
arg(arg&&) = delete;
arg& operator=(arg&&) = delete;
arg(const arg&) = delete;
arg& operator=(const arg&) = delete;
template < typename T
, std::enable_if_t<!std::is_same_v<std::decay_t<T>, arg>, int> = 0
, std::enable_if_t<!std::is_same_v<std::decay_t<T>, inst>, int> = 0
, std::enable_if_t<!std::is_same_v<std::decay_t<T>, value>, int> = 0 >
explicit arg(T&& v);
explicit arg(value& v);
explicit arg(value&& v);
explicit arg(const value& v);
explicit arg(const value&& v);
template < typename To >
To cast() const;
private:
void* data_{};
};
}
namespace meta_hpp
{
template < typename T
, std::enable_if_t<!std::is_same_v<std::decay_t<T>, arg>, int>
, std::enable_if_t<!std::is_same_v<std::decay_t<T>, inst>, int>
, std::enable_if_t<!std::is_same_v<std::decay_t<T>, value>, int> >
arg::arg(T&& v)
: arg_base{typename_arg<T&&>}
, data_{const_cast<stdex::remove_cvref_t<T>*>(std::addressof(v))} {}
inline arg::arg(value& v)
: arg_base{v}
, data_{const_cast<void*>(v.data())} {}
inline arg::arg(value&& v)
: arg_base{v}
, data_{const_cast<void*>(v.data())} {}
inline arg::arg(const value& v)
: arg_base{v}
, data_{const_cast<void*>(v.data())} {}
inline arg::arg(const value&& v)
: arg_base{v}
, data_{const_cast<void*>(v.data())} {}
template < typename To >
To arg::cast() const {
if ( !can_cast_to<To>() ) {
throw std::logic_error("bad argument cast");
}
if constexpr ( std::is_pointer_v<To> ) {
return *static_cast<To*>(data_);
}
if constexpr ( std::is_reference_v<To> ) {
using raw_type = stdex::remove_cvref_t<To>;
if constexpr ( std::is_lvalue_reference_v<To> ) {
return *static_cast<raw_type*>(data_);
}
if constexpr ( std::is_rvalue_reference_v<To> ) {
return std::move(*static_cast<raw_type*>(data_));
}
}
if constexpr ( !std::is_pointer_v<To> && !std::is_reference_v<To> ) {
using raw_type = std::remove_cv_t<To>;
if ( ref_type() == ref_types::ref ) {
if constexpr ( std::is_constructible_v<To, raw_type&> ) {
return To{*static_cast<raw_type*>(data_)};
}
}
if ( ref_type() == ref_types::cref ) {
if constexpr ( std::is_constructible_v<To, const raw_type&> ) {
return To{std::as_const(*static_cast<raw_type*>(data_))};
}
}
if ( ref_type() == ref_types::rref ) {
if constexpr ( std::is_constructible_v<To, raw_type&&> ) {
return To{std::move(*static_cast<raw_type*>(data_))};
}
}
if ( ref_type() == ref_types::crref ) {
if constexpr ( std::is_constructible_v<To, const raw_type&&> ) {
return To{std::move(std::as_const(*static_cast<raw_type*>(data_)))};
}
}
}
throw std::logic_error("bad argument cast");
}
}

View File

@@ -1,229 +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)
******************************************************************************/
#pragma once
#include "../meta_fwd.hpp"
#include "value.hpp"
namespace meta_hpp
{
class inst_base {
public:
enum class ref_types {
ref,
rref,
cref,
crref,
};
public:
inst_base() = delete;
inst_base(inst_base&&) = delete;
inst_base& operator=(inst_base&&) = delete;
inst_base(const inst_base&) = delete;
inst_base& operator=(const inst_base&) = delete;
template < typename T, std::enable_if_t<
std::is_lvalue_reference_v<T> && std::is_class_v<std::remove_reference_t<T>>
, int> = 0>
explicit inst_base(typename_arg_t<T>);
template < typename T, std::enable_if_t<
std::is_class_v<T> ||
(std::is_rvalue_reference_v<T> && std::is_class_v<std::remove_reference_t<T>>)
, int> = 0>
explicit inst_base(typename_arg_t<T>);
explicit inst_base(value& v);
explicit inst_base(value&& v);
explicit inst_base(const value& v);
explicit inst_base(const value&& v);
bool is_const() const noexcept;
bool is_lvalue() const noexcept;
bool is_rvalue() const noexcept;
any_type raw_type() const noexcept;
ref_types ref_type() const noexcept;
template < typename To >
bool can_cast_to() const noexcept;
private:
any_type raw_type_{};
ref_types ref_type_{};
};
}
namespace meta_hpp
{
template < typename T, std::enable_if_t<
std::is_lvalue_reference_v<T> && std::is_class_v<std::remove_reference_t<T>>
, int> >
inst_base::inst_base(typename_arg_t<T>)
: raw_type_{type_db::get<stdex::remove_cvref_t<T>>()}
, ref_type_{std::is_const_v<std::remove_reference_t<T>> ? ref_types::cref : ref_types::ref} {}
template < typename T, std::enable_if_t<
std::is_class_v<T> ||
(std::is_rvalue_reference_v<T> && std::is_class_v<std::remove_reference_t<T>>)
, int> >
inst_base::inst_base(typename_arg_t<T>)
: raw_type_{type_db::get<stdex::remove_cvref_t<T>>()}
, ref_type_{std::is_const_v<std::remove_reference_t<T>> ? ref_types::crref : ref_types::rref} {}
inline inst_base::inst_base(value& v)
: raw_type_{v.type()}
, ref_type_{ref_types::ref} {}
inline inst_base::inst_base(value&& v)
: raw_type_{v.type()}
, ref_type_{ref_types::rref} {}
inline inst_base::inst_base(const value& v)
: raw_type_{v.type()}
, ref_type_{ref_types::cref} {}
inline inst_base::inst_base(const value&& v)
: raw_type_{v.type()}
, ref_type_{ref_types::crref} {}
inline bool inst_base::is_const() const noexcept {
return ref_type_ == ref_types::cref
|| ref_type_ == ref_types::crref;
}
inline bool inst_base::is_lvalue() const noexcept {
return ref_type_ == ref_types::ref
|| ref_type_ == ref_types::cref;
}
inline bool inst_base::is_rvalue() const noexcept {
return ref_type_ == ref_types::rref
|| ref_type_ == ref_types::crref;
}
inline any_type inst_base::raw_type() const noexcept {
return raw_type_;
}
inline inst_base::ref_types inst_base::ref_type() const noexcept {
return ref_type_;
}
template < typename To >
bool inst_base::can_cast_to() const noexcept {
static_assert(
std::is_class_v<To> ||
(std::is_reference_v<To> && std::is_class_v<std::remove_reference_t<To>>));
constexpr bool to_const = std::is_const_v<std::remove_reference_t<To>>;
if constexpr ( !to_const ) {
if ( is_const() ) {
return false;
}
}
if constexpr ( std::is_lvalue_reference_v<To> ) {
if ( !is_lvalue() ) {
return false;
}
}
if constexpr ( std::is_rvalue_reference_v<To> ) {
if ( !is_rvalue() ) {
return false;
}
}
using to_raw_type = stdex::remove_cvref_t<To>;
return raw_type() == type_db::get<to_raw_type>();
}
}
namespace meta_hpp
{
class inst final : public inst_base {
public:
inst() = delete;
inst(inst&&) = delete;
inst& operator=(inst&&) = delete;
inst(const inst&) = delete;
inst& operator=(const inst&) = delete;
template < typename T
, std::enable_if_t<!std::is_same_v<std::decay_t<T>, arg>, int> = 0
, std::enable_if_t<!std::is_same_v<std::decay_t<T>, inst>, int> = 0
, std::enable_if_t<!std::is_same_v<std::decay_t<T>, value>, int> = 0 >
explicit inst(T&& v);
explicit inst(value& v);
explicit inst(value&& v);
explicit inst(const value& v);
explicit inst(const value&& v);
template < typename To >
decltype(auto) cast() const;
private:
void* data_{};
};
}
namespace meta_hpp
{
template < typename T
, std::enable_if_t<!std::is_same_v<std::decay_t<T>, arg>, int>
, std::enable_if_t<!std::is_same_v<std::decay_t<T>, inst>, int>
, std::enable_if_t<!std::is_same_v<std::decay_t<T>, value>, int> >
inst::inst(T&& v)
: inst_base{typename_arg<T&&>}
, data_{const_cast<stdex::remove_cvref_t<T>*>(std::addressof(v))} {}
inline inst::inst(value& v)
: inst_base{v}
, data_{const_cast<void*>(v.data())} {}
inline inst::inst(value&& v)
: inst_base{v}
, data_{const_cast<void*>(v.data())} {}
inline inst::inst(const value& v)
: inst_base{v}
, data_{const_cast<void*>(v.data())} {}
inline inst::inst(const value&& v)
: inst_base{v}
, data_{const_cast<void*>(v.data())} {}
template < typename To >
decltype(auto) inst::cast() const {
if ( !can_cast_to<To>() ) {
throw std::logic_error("bad inst cast");
}
if constexpr ( std::is_reference_v<To> ) {
using raw_type_with_cv = std::remove_reference_t<To>;
if constexpr ( std::is_lvalue_reference_v<To> ) {
return *static_cast<raw_type_with_cv*>(data_);
}
if constexpr ( std::is_rvalue_reference_v<To> ) {
return std::move(*static_cast<raw_type_with_cv*>(data_));
}
}
if constexpr ( !std::is_reference_v<To>) {
using raw_type_with_cv = To;
return *static_cast<raw_type_with_cv*>(data_);
}
}
}

View File

@@ -1,376 +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)
******************************************************************************/
#pragma once
#include "../meta_fwd.hpp"
namespace meta_hpp
{
class value final {
public:
value() = delete;
value(value&& other);
value(const value& other);
value& operator=(value&& other);
value& operator=(const value& other);
template < typename T
, typename Tp = std::decay_t<T>
, std::enable_if_t<!std::is_same_v<Tp, arg>, int> = 0
, std::enable_if_t<!std::is_same_v<Tp, inst>, int> = 0
, std::enable_if_t<!std::is_same_v<Tp, value>, int> = 0 >
explicit value(T&& val);
template < typename T
, typename Tp = std::decay_t<T>
, std::enable_if_t<!std::is_same_v<Tp, arg>, int> = 0
, std::enable_if_t<!std::is_same_v<Tp, inst>, int> = 0
, std::enable_if_t<!std::is_same_v<Tp, value>, int> = 0 >
value& operator=(T&& val);
void swap(value& other) noexcept;
const any_type& type() const noexcept;
void* data() noexcept;
const void* data() const noexcept;
const void* cdata() const noexcept;
template < typename T, typename Tp = std::decay_t<T> >
Tp& cast() &;
template < typename T, typename Tp = std::decay_t<T> >
Tp&& cast() &&;
template < typename T, typename Tp = std::decay_t<T> >
const Tp& cast() const &;
template < typename T, typename Tp = std::decay_t<T> >
const Tp&& cast() const &&;
template < typename T, typename Tp = std::decay_t<T> >
Tp* try_cast() noexcept;
template < typename T, typename Tp = std::decay_t<T> >
const Tp* try_cast() const noexcept;
template < typename T >
friend bool operator==(const value& l, const T& r);
template < typename T >
friend bool operator==(const T& l, const value& r);
friend bool operator==(const value& l, const value& r);
friend std::istream& operator>>(std::istream& os, value& v);
friend std::ostream& operator<<(std::ostream& os, const value& v);
private:
struct traits;
std::any raw_{};
const traits* traits_{};
};
inline void swap(value& l, value& r) noexcept {
l.swap(r);
}
}
namespace meta_hpp::detail
{
template < typename T, typename = void >
struct has_value_type_equality_operator
: std::false_type {};
template < typename T >
struct has_value_type_equality_operator<T, std::void_t<decltype(
std::declval<const T&>() == std::declval<const T&>()
)>> : std::true_type {};
template < typename T >
inline constexpr bool has_value_type_equality_operator_v = has_value_type_equality_operator<T>::value;
template < typename T, std::enable_if_t<
has_value_type_equality_operator_v<T>
, int> = 0 >
bool value_equals_function(const value& l, const value& r) {
assert(l.type() == r.type());
return l.cast<T>() == r.cast<T>();
}
template < typename T, std::enable_if_t<
!has_value_type_equality_operator_v<T>
, int> = 0 >
bool value_equals_function([[maybe_unused]] const value& l, [[maybe_unused]] const value& r) {
throw std::logic_error("value type doesn't have equality operator");
}
}
namespace meta_hpp::detail
{
template < typename T, typename = void >
struct has_value_type_istream_operator
: std::false_type {};
template < typename T >
struct has_value_type_istream_operator<T, std::void_t<decltype(
std::declval<std::istream&>() >> std::declval<T&>()
)>> : std::true_type {};
template < typename T >
inline constexpr bool has_value_type_istream_operator_v = has_value_type_istream_operator<T>::value;
template < typename T, std::enable_if_t<
has_value_type_istream_operator_v<T>
, int> = 0 >
void value_istream_function(std::istream& os, value& v) {
os >> v.cast<T>();
}
template < typename T, std::enable_if_t<
!has_value_type_istream_operator_v<T>
, int> = 0 >
void value_istream_function([[maybe_unused]] std::istream& os, [[maybe_unused]] value& v) {
throw std::logic_error("value type doesn't have istream operator");
}
}
namespace meta_hpp::detail
{
template < typename T, typename = void >
struct has_value_type_ostream_operator
: std::false_type {};
template < typename T >
struct has_value_type_ostream_operator<T, std::void_t<decltype(
std::declval<std::ostream&>() << std::declval<const T&>()
)>> : std::true_type {};
template < typename T >
inline constexpr bool has_value_type_ostream_operator_v = has_value_type_ostream_operator<T>::value;
template < typename T, std::enable_if_t<
has_value_type_ostream_operator_v<T>
, int> = 0 >
void value_ostream_function(std::ostream& os, const value& v) {
os << v.cast<T>();
}
template < typename T, std::enable_if_t<
!has_value_type_ostream_operator_v<T>
, int> = 0 >
void value_ostream_function([[maybe_unused]] std::ostream& os, [[maybe_unused]] const value& v) {
throw std::logic_error("value type doesn't have ostream operator");
}
}
namespace meta_hpp
{
struct value::traits final {
const any_type type;
void* (*const data)(value&) noexcept;
const void* (*const cdata)(const value&) noexcept;
bool (*const equals)(const value&, const value&);
void (*const move_ctor)(std::any&, value&&);
void (*const copy_ctor)(std::any&, const value&);
void (*const istream)(std::istream&, value&);
void (*const ostream)(std::ostream&, const value&);
template < typename T >
static const traits* get() noexcept;
};
template < typename T >
const value::traits* value::traits::get() noexcept {
static const traits traits{
// type
type_db::get<T>(),
// data
+[](value& v) noexcept -> void* {
return v.try_cast<T>();
},
// cdata
+[](const value& v) noexcept -> const void* {
return v.try_cast<T>();
},
// equals
&detail::value_equals_function<T>,
// move_ctor
+[](std::any& dst, value&& src) {
if constexpr ( std::is_move_constructible_v<T> ) {
dst.emplace<T>(std::move(src).cast<T>());
} else {
throw std::logic_error("value type is not move constructible");
}
},
// copy_ctor
+[](std::any& dst, const value& src) {
if constexpr ( std::is_copy_constructible_v<T> ) {
dst.emplace<T>(src.cast<T>());
} else {
throw std::logic_error("value type is not copy constructible");
}
},
// istream
&detail::value_istream_function<T>,
// ostream
&detail::value_ostream_function<T>,
};
return &traits;
}
}
namespace meta_hpp
{
inline value::value(value&& other) {
traits_ = other.traits_;
traits_->move_ctor(raw_, std::move(other));
}
inline value::value(const value& other) {
traits_ = other.traits_;
traits_->copy_ctor(raw_, other);
}
inline value& value::operator=(value&& other) {
if ( this != &other ) {
traits_ = other.traits_;
traits_->move_ctor(raw_, std::move(other));
}
return *this;
}
inline value& value::operator=(const value& other) {
if ( this != &other ) {
traits_ = other.traits_;
traits_->copy_ctor(raw_, other);
}
return *this;
}
template < typename T, typename Tp
, std::enable_if_t<!std::is_same_v<Tp, arg>, int>
, std::enable_if_t<!std::is_same_v<Tp, inst>, int>
, std::enable_if_t<!std::is_same_v<Tp, value>, int> >
value::value(T&& val)
: raw_{std::forward<T>(val)}
, traits_{traits::get<Tp>()} {}
template < typename T, typename Tp
, std::enable_if_t<!std::is_same_v<Tp, arg>, int>
, std::enable_if_t<!std::is_same_v<Tp, inst>, int>
, std::enable_if_t<!std::is_same_v<Tp, value>, int> >
value& value::operator=(T&& val) {
raw_ = std::forward<T>(val);
traits_ = type_db::get<Tp>();
return *this;
}
inline void value::swap(value& other) noexcept {
using std::swap;
swap(raw_, other.raw_);
swap(traits_, other.traits_);
}
inline const any_type& value::type() const noexcept {
return traits_->type;
}
inline void* value::data() noexcept {
return traits_->data(*this);
}
inline const void* value::data() const noexcept {
return traits_->cdata(*this);
}
inline const void* value::cdata() const noexcept {
return traits_->cdata(*this);
}
template < typename T, typename Tp >
Tp& value::cast() & {
if ( type() != type_db::get<Tp>() ) {
throw std::logic_error("bad value cast");
}
return std::any_cast<Tp&>(raw_);
}
template < typename T, typename Tp >
Tp&& value::cast() && {
if ( type() != type_db::get<Tp>() ) {
throw std::logic_error("bad value cast");
}
return std::move(std::any_cast<Tp&>(raw_));
}
template < typename T, typename Tp >
const Tp& value::cast() const & {
if ( type() != type_db::get<Tp>() ) {
throw std::logic_error("bad value cast");
}
return std::any_cast<const Tp&>(raw_);
}
template < typename T, typename Tp >
const Tp&& value::cast() const && {
if ( type() != type_db::get<Tp>() ) {
throw std::logic_error("bad value cast");
}
return std::move(std::any_cast<const Tp&>(raw_));
}
template < typename T, typename Tp >
Tp* value::try_cast() noexcept {
return std::any_cast<Tp>(&raw_);
}
template < typename T, typename Tp >
const Tp* value::try_cast() const noexcept {
return std::any_cast<Tp>(&raw_);
}
}
namespace meta_hpp
{
template < typename T >
bool operator==(const value& l, const T& r) {
return l.type() == type_db::get<T>()
&& std::equal_to<>{}(l.cast<T>(), r);
}
template < typename T >
bool operator==(const T& l, const value& r) {
return type_db::get<T>() == r.type()
&& std::equal_to<>{}(l, r.cast<T>());
}
inline bool operator==(const value& l, const value& r) {
return l.type() == r.type()
&& l.traits_->equals(l, r);
}
inline std::istream& operator>>(std::istream& is, value& v) {
v.traits_->istream(is, v);
return is;
}
inline std::ostream& operator<<(std::ostream& os, const value& v) {
v.traits_->ostream(os, v);
return os;
}
}

View File

@@ -1,9 +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)
******************************************************************************/
#pragma once
#include "../../meta_tests.hpp"

View File

@@ -1,44 +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 "_infos_fwd.hpp"
namespace
{
using namespace meta_hpp;
using namespace std::string_literals;
}
namespace
{
class base {
public:
virtual ~base() {}
};
class derived final : public base {
public:
};
struct empty final {};
}
TEST_CASE("features/infos/base") {
registry db;
db(
class_<base>{"base"},
class_<derived>{"derived"}(
base_<base>{}
)
);
REQUIRE(db.get_class_by_path("derived"));
const class_info derived_info = db.get_class_by_path("derived");
CHECK(derived_info.is_derived_from<base>());
CHECK_FALSE(derived_info.is_derived_from<empty>());
}

View File

@@ -1,94 +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 "_infos_fwd.hpp"
namespace
{
using namespace meta_hpp;
using namespace std::string_literals;
}
namespace
{
class shape {
public:
virtual ~shape() {}
virtual int area() const = 0;
};
class rectangle : public shape {
public:
rectangle(const rectangle& other) {
width_ = other.width_;
height_ = other.height_;
}
rectangle& operator=(const rectangle& other) {
if ( this != &other ) {
return *this;
}
width_ = other.width_;
height_ = other.height_;
return *this;
}
rectangle(int width, int height)
: width_{width}
, height_{height} {}
int area() const override {
return width_ * height_;
}
int width() const noexcept {
return width_;
}
int height() const noexcept {
return height_;
}
private:
int width_{};
int height_{};
};
}
TEST_CASE("features/infos/class") {
registry db;
db(
class_<shape>{"shape"}(
method_{"area", &shape::area}
),
class_<rectangle>{"rectangle"}(
base_<shape>{},
ctor_<int, int>{},
method_{"width", &rectangle::width},
method_{"height", &rectangle::height}
)
);
SUBCASE("base") {
REQUIRE(db.get_class_by_path("shape"));
const class_info shape_info = db.get_class_by_path("shape");
CHECK(shape_info.name() == "shape");
CHECK(shape_info.type() == type_db::get<shape>());
CHECK_FALSE(shape_info.is_derived_from<shape>());
CHECK_FALSE(shape_info.is_derived_from<rectangle>());
}
SUBCASE("derived") {
REQUIRE(db.get_class_by_path("rectangle"));
const class_info rectangle_info = db.get_class_by_path("rectangle");
CHECK(rectangle_info.name() == "rectangle");
CHECK(rectangle_info.type() == type_db::get<rectangle>());
CHECK(rectangle_info.is_derived_from<shape>());
CHECK_FALSE(rectangle_info.is_derived_from<rectangle>());
}
}

View File

@@ -1,201 +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 "_infos_fwd.hpp"
namespace
{
using namespace meta_hpp;
using namespace std::string_literals;
}
namespace
{
struct ivec2 {
int x{};
int y{};
[[maybe_unused]] ivec2() = default;
[[maybe_unused]] ivec2(const ivec2& other) = default;
[[maybe_unused]] explicit ivec2(int v): x{v}, y{v} {}
[[maybe_unused]] ivec2(int x, int y): x{x}, y{y} {}
};
[[maybe_unused]] bool operator==(const ivec2& l, const ivec2& r) noexcept {
return l.x == r.x && l.y == r.y;
}
}
TEST_CASE("features/infos/ctor") {
registry db;
db(
namespace_{"vmath"}(
class_<ivec2>{"ivec2"}(
ctor_<>{}(data_{"info", "void ctor"s}),
ctor_<const ivec2&>{}(data_{"info", "copy ctor"s}),
ctor_<int>{}(data_{"info", "int ctor"s}),
ctor_<int, int>{}(data_{"info", "int,int ctor"s})
)
)
);
const class_info ivec2_info = db.get_class_by_path("vmath::ivec2");
REQUIRE(ivec2_info);
SUBCASE("void") {
const ctor_info ci = ivec2_info.get_ctor_by_args();
REQUIRE(ci);
REQUIRE(ci.get_data_by_name("info"));
CHECK(ci.get_data_by_name("info").value() == "void ctor"s);
{
const ctor_info ci2 = ivec2_info.get_ctor_by_args(std::array<any_type, 0>{});
const ctor_info ci3 = ivec2_info.get_ctor_by_args(std::vector<any_type>{});
REQUIRE(ci2);
REQUIRE(ci3);
CHECK(ci.type() == ci2.type());
CHECK(ci.type() == ci2.type());
}
{
CHECK(ci.is_invocable_with<>());
CHECK_FALSE(ci.is_invocable_with<int>());
CHECK_FALSE(ci.is_invocable_with<const int>());
CHECK_FALSE(ci.is_invocable_with<int&>());
CHECK_FALSE(ci.is_invocable_with<const int&>());
CHECK_FALSE(ci.is_invocable_with<int&&>());
CHECK_FALSE(ci.is_invocable_with<const int&&>());
}
{
CHECK(ci.invoke() == ivec2{});
CHECK_THROWS(ci.invoke(42));
}
}
SUBCASE("int") {
const ctor_info ci = ivec2_info.get_ctor_by_args<int>();
REQUIRE(ci);
REQUIRE(ci.get_data_by_name("info"));
CHECK(ci.get_data_by_name("info").value() == "int ctor"s);
{
const ctor_info ci2 = ivec2_info.get_ctor_by_args(std::array<any_type, 1>{
type_db::get<int>()});
const ctor_info ci3 = ivec2_info.get_ctor_by_args(std::vector<any_type>{
type_db::get<int>()});
REQUIRE(ci2);
REQUIRE(ci3);
CHECK(ci.type() == ci2.type());
CHECK(ci.type() == ci2.type());
}
{
CHECK_FALSE(ci.is_invocable_with<>());
CHECK(ci.is_invocable_with<int>());
CHECK(ci.is_invocable_with<const int>());
CHECK(ci.is_invocable_with<int&>());
CHECK(ci.is_invocable_with<const int&>());
CHECK(ci.is_invocable_with<int&&>());
CHECK(ci.is_invocable_with<const int&&>());
}
{
CHECK_THROWS(ci.invoke());
CHECK(ci.invoke(42) == ivec2{42});
}
}
SUBCASE("const ivec2&") {
const ctor_info ci = ivec2_info.get_ctor_by_args<const ivec2&>();
REQUIRE(ci);
REQUIRE(ci.get_data_by_name("info"));
CHECK(ci.get_data_by_name("info").value() == "copy ctor"s);
{
const ctor_info ci2 = ivec2_info.get_ctor_by_args(std::array<any_type, 1>{
type_db::get<const ivec2&>()});
const ctor_info ci3 = ivec2_info.get_ctor_by_args(std::vector<any_type>{
type_db::get<const ivec2&>()});
REQUIRE(ci2);
REQUIRE(ci3);
CHECK(ci.type() == ci2.type());
CHECK(ci.type() == ci2.type());
}
{
CHECK_FALSE(ci.is_invocable_with<>());
CHECK_FALSE(ci.is_invocable_with<int>());
CHECK_FALSE(ci.is_invocable_with<const int>());
CHECK_FALSE(ci.is_invocable_with<int&>());
CHECK_FALSE(ci.is_invocable_with<const int&>());
CHECK_FALSE(ci.is_invocable_with<int&&>());
CHECK_FALSE(ci.is_invocable_with<const int&&>());
CHECK(ci.is_invocable_with<ivec2>());
CHECK(ci.is_invocable_with<ivec2&>());
CHECK(ci.is_invocable_with<const ivec2&>());
CHECK(ci.is_invocable_with<ivec2&&>());
CHECK(ci.is_invocable_with<const ivec2&&>());
}
{
CHECK_THROWS(ci.invoke());
CHECK_THROWS(ci.invoke(42));
CHECK(ci.invoke(ivec2{21,42}) == ivec2{21,42});
}
}
SUBCASE("int,int") {
const ctor_info ci = ivec2_info.get_ctor_by_args<int,int>();
REQUIRE(ci);
REQUIRE(ci.get_data_by_name("info"));
CHECK(ci.get_data_by_name("info").value() == "int,int ctor"s);
{
const ctor_info ci2 = ivec2_info.get_ctor_by_args(std::array<any_type, 2>{
type_db::get<int>(),
type_db::get<int>()});
const ctor_info ci3 = ivec2_info.get_ctor_by_args(std::vector<any_type>{
type_db::get<int>(),
type_db::get<int>()});
REQUIRE(ci2);
REQUIRE(ci3);
CHECK(ci.type() == ci2.type());
CHECK(ci.type() == ci2.type());
}
{
CHECK_FALSE(ci.is_invocable_with<>());
CHECK_FALSE(ci.is_invocable_with<int>());
CHECK_FALSE(ci.is_invocable_with<const int>());
CHECK_FALSE(ci.is_invocable_with<int&>());
CHECK_FALSE(ci.is_invocable_with<const int&>());
CHECK_FALSE(ci.is_invocable_with<int&&>());
CHECK_FALSE(ci.is_invocable_with<const int&&>());
CHECK(ci.is_invocable_with<int, int>());
CHECK(ci.is_invocable_with<int&, int&&>());
CHECK(ci.is_invocable_with<const int&, const int&&>());
}
{
CHECK_THROWS(ci.invoke());
CHECK_THROWS(ci.invoke(42));
CHECK_THROWS(ci.invoke(ivec2{21,42}));
CHECK(ci.invoke(21,42) == ivec2{21,42});
}
}
}

View File

@@ -1,14 +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 "_infos_fwd.hpp"
namespace
{
}
TEST_CASE("features/infos/data") {
}

View File

@@ -1,14 +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 "_infos_fwd.hpp"
namespace
{
}
TEST_CASE("features/infos/enum") {
}

View File

@@ -1,14 +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 "_infos_fwd.hpp"
namespace
{
}
TEST_CASE("features/infos/evalue") {
}

View File

@@ -1,95 +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 "_infos_fwd.hpp"
namespace
{
using namespace meta_hpp;
using namespace std::string_literals;
}
namespace
{
struct ivec2 {
int x{};
int y{};
[[maybe_unused]] ivec2() = default;
[[maybe_unused]] ivec2(const ivec2& other) = default;
[[maybe_unused]] explicit ivec2(int v): x{v}, y{v} {}
[[maybe_unused]] ivec2(int x, int y): x{x}, y{y} {}
};
bool operator==(const ivec2& l, const ivec2& r) noexcept {
return l.x == r.x && l.y == r.y;
}
ivec2 iadd(const ivec2& l, const ivec2& r) noexcept {
return {l.x + r.x, l.y + r.y};
}
int ilength2(const ivec2& v) noexcept {
return v.x * v.x + v.y * v.y;
}
}
TEST_CASE("features/infos/function") {
registry db;
db(
namespace_{"vmath"}(
class_<ivec2>{"ivec2"},
function_{"iadd", &iadd}(data_{"info", "iadd function"s}),
function_{"ilength2", &ilength2}(data_{"info", "ilength2 function"s})
)
);
SUBCASE("iadd") {
const function_info fi = db.get_function_by_path("vmath::iadd");
REQUIRE(fi);
REQUIRE(fi.get_data_by_name("info"));
CHECK(fi.get_data_by_name("info").value() == "iadd function"s);
CHECK_FALSE(fi.is_invocable_with());
CHECK_FALSE(fi.is_invocable_with<int>());
CHECK_FALSE(fi.is_invocable_with<ivec2, int>());
CHECK_FALSE(fi.is_invocable_with<ivec2, ivec2, int>());
CHECK(fi.is_invocable_with<ivec2, ivec2>());
CHECK(fi.is_invocable_with<ivec2&&, const ivec2&>());
CHECK_THROWS(fi.invoke());
CHECK_THROWS(fi.invoke(42));
CHECK_THROWS(fi.invoke(ivec2{}, 42));
CHECK(fi.invoke(ivec2{1,2},ivec2{3,4}));
CHECK(fi.invoke(ivec2{1,2},ivec2{3,4}).value() == ivec2{4,6});
}
SUBCASE("ilength2") {
const function_info fi = db.get_function_by_path("vmath::ilength2");
REQUIRE(fi);
REQUIRE(fi.get_data_by_name("info"));
CHECK(fi.get_data_by_name("info").value() == "ilength2 function"s);
CHECK_FALSE(fi.is_invocable_with());
CHECK_FALSE(fi.is_invocable_with<int>());
CHECK_FALSE(fi.is_invocable_with<ivec2, int>());
CHECK(fi.is_invocable_with<ivec2>());
CHECK(fi.is_invocable_with<const ivec2&>());
CHECK_THROWS(fi.invoke());
CHECK_THROWS(fi.invoke(42));
CHECK_THROWS(fi.invoke(ivec2{}, 42));
CHECK(fi.invoke(ivec2{2,3}));
CHECK(fi.invoke(ivec2{2,3}).value() == 13);
}
}

View File

@@ -1,163 +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 "_infos_fwd.hpp"
namespace
{
using namespace meta_hpp;
using namespace std::string_literals;
}
namespace
{
struct ivec2 {
int x{};
int y{};
[[maybe_unused]] ivec2() = default;
[[maybe_unused]] explicit ivec2(int v): x{v}, y{v} {}
[[maybe_unused]] ivec2(int x, int y): x{x}, y{y} {}
};
struct ipnt2 {
const int x{};
const int y{};
[[maybe_unused]] ipnt2() = default;
[[maybe_unused]] explicit ipnt2(int v): x{v}, y{v} {}
[[maybe_unused]] ipnt2(int x, int y): x{x}, y{y} {}
};
bool operator==(const ivec2& l, const ivec2& r) noexcept {
return l.x == r.x && l.y == r.y;
}
bool operator==(const ipnt2& l, const ipnt2& r) noexcept {
return l.x == r.x && l.y == r.y;
}
}
TEST_CASE("features/infos/member") {
registry db;
db(
namespace_{"vmath"}(
class_<ivec2>{"ivec2"}(
member_{"x", &ivec2::x},
member_{"y", &ivec2::y}
),
class_<ipnt2>{"ipnt2"}(
member_{"x", &ipnt2::x},
member_{"y", &ipnt2::y}
)
)
);
SUBCASE("non_const") {
const member_info x_mi = db.get_member_by_path("vmath::ivec2::x");
const member_info y_mi = db.get_member_by_path("vmath::ivec2::y");
REQUIRE(x_mi);
REQUIRE(y_mi);
{
CHECK(x_mi.name() == "x");
CHECK(x_mi.type().class_type() == type_db::get<ivec2>());
CHECK(x_mi.type().value_type() == type_db::get<int>());
CHECK(y_mi.name() == "y");
CHECK(y_mi.type().class_type() == type_db::get<ivec2>());
CHECK(y_mi.type().value_type() == type_db::get<int>());
}
{
ivec2 v{1,2};
CHECK(x_mi.get(v) == 1);
CHECK(x_mi.get(std::as_const(v)) == 1);
CHECK(x_mi.get(std::move(v)) == 1);
CHECK(x_mi.get(std::move(std::as_const(v))) == 1);
CHECK(y_mi.get(v) == 2);
CHECK(y_mi.get(std::as_const(v)) == 2);
CHECK(y_mi.get(std::move(v)) == 2);
CHECK(y_mi.get(std::move(std::as_const(v))) == 2);
static_assert(std::is_invocable_v<decltype(&ivec2::x), ivec2&>);
static_assert(std::is_invocable_v<decltype(&ivec2::x), const ivec2&>);
static_assert(std::is_invocable_v<decltype(&ivec2::x), ivec2&&>);
static_assert(std::is_invocable_v<decltype(&ivec2::x), const ivec2&&>);
}
{
ivec2 v{1,2};
CHECK_NOTHROW(x_mi.set(v, 10)); CHECK(v.x == 10);
CHECK_THROWS(x_mi.set(std::as_const(v), 11)); CHECK(v.x == 10);
CHECK_NOTHROW(x_mi.set(std::move(v), 12)); CHECK(v.x == 12);
CHECK_THROWS(x_mi.set(std::move(std::as_const(v)), 13)); CHECK(v.x == 12);
CHECK_NOTHROW(y_mi.set(v, 20)); CHECK(v.y == 20);
CHECK_THROWS(y_mi.set(std::as_const(v), 21)); CHECK(v.y == 20);
CHECK_NOTHROW(y_mi.set(std::move(v), 22)); CHECK(v.y == 22);
CHECK_THROWS(y_mi.set(std::move(std::as_const(v)), 23)); CHECK(v.y == 22);
CHECK(v == ivec2{12,22});
}
}
SUBCASE("const") {
const member_info x_mi = db.get_member_by_path("vmath::ipnt2::x");
const member_info y_mi = db.get_member_by_path("vmath::ipnt2::y");
REQUIRE(x_mi);
REQUIRE(y_mi);
{
CHECK(x_mi.name() == "x");
CHECK(x_mi.type().class_type() == type_db::get<ipnt2>());
CHECK(x_mi.type().value_type() == type_db::get<const int>());
CHECK(y_mi.name() == "y");
CHECK(y_mi.type().class_type() == type_db::get<ipnt2>());
CHECK(y_mi.type().value_type() == type_db::get<const int>());
}
{
ipnt2 v{1,2};
CHECK(x_mi.get(v) == 1);
CHECK(x_mi.get(std::as_const(v)) == 1);
CHECK(x_mi.get(std::move(v)) == 1);
CHECK(x_mi.get(std::move(std::as_const(v))) == 1);
CHECK(y_mi.get(v) == 2);
CHECK(y_mi.get(std::as_const(v)) == 2);
CHECK(y_mi.get(std::move(v)) == 2);
CHECK(y_mi.get(std::move(std::as_const(v))) == 2);
static_assert(std::is_invocable_v<decltype(&ipnt2::x), ipnt2&>);
static_assert(std::is_invocable_v<decltype(&ipnt2::x), const ipnt2&>);
static_assert(std::is_invocable_v<decltype(&ipnt2::x), ipnt2&&>);
static_assert(std::is_invocable_v<decltype(&ipnt2::x), const ipnt2&&>);
}
{
ipnt2 v{1,2};
CHECK_THROWS(x_mi.set(v, 10)); CHECK(v.x == 1);
CHECK_THROWS(x_mi.set(std::as_const(v), 11)); CHECK(v.x == 1);
CHECK_THROWS(x_mi.set(std::move(v), 12)); CHECK(v.x == 1);
CHECK_THROWS(x_mi.set(std::move(std::as_const(v)), 13)); CHECK(v.x == 1);
CHECK_THROWS(y_mi.set(v, 20)); CHECK(v.y == 2);
CHECK_THROWS(y_mi.set(std::as_const(v), 21)); CHECK(v.y == 2);
CHECK_THROWS(y_mi.set(std::move(v), 22)); CHECK(v.y == 2);
CHECK_THROWS(y_mi.set(std::move(std::as_const(v)), 23)); CHECK(v.y == 2);
CHECK(v == ipnt2{1,2});
}
}
}

View File

@@ -1,786 +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 "_infos_fwd.hpp"
namespace
{
using namespace meta_hpp;
using namespace std::string_literals;
}
namespace
{
struct clazz {
clazz() = default;
clazz(clazz&&) = delete;
clazz(const clazz&) = delete;
clazz& operator=(clazz&&) = delete;
clazz& operator=(const clazz&) = delete;
//
int non_const_method() { return 1; }
int non_const_method_noexcept() noexcept { return 2; }
int const_method() const { return 3; }
int const_method_noexcept() const noexcept { return 4; }
int non_const_method_ref() & { return 5; }
int non_const_method_noexcept_ref() & noexcept { return 6; }
int const_method_ref() const & { return 7; }
int const_method_noexcept_ref() const & noexcept { return 8; }
int non_const_method_rref() && { return 9; }
int non_const_method_noexcept_rref() && noexcept { return 10; }
int const_method_rref() const && { return 11; }
int const_method_noexcept_rref() const && noexcept { return 12; }
//
int non_const_method_volatile() volatile { return 1; }
int non_const_method_noexcept_volatile() volatile noexcept { return 2; }
int const_method_volatile() volatile const { return 3; }
int const_method_noexcept_volatile() volatile const noexcept { return 4; }
int non_const_method_ref_volatile() volatile & { return 5; }
int non_const_method_noexcept_ref_volatile() volatile & noexcept { return 6; }
int const_method_ref_volatile() volatile const & { return 7; }
int const_method_noexcept_ref_volatile() volatile const & noexcept { return 8; }
int non_const_method_rref_volatile() volatile && { return 9; }
int non_const_method_noexcept_rref_volatile() volatile && noexcept { return 10; }
int const_method_rref_volatile() volatile const && { return 11; }
int const_method_noexcept_rref_volatile() volatile const && noexcept { return 12; }
};
struct clazz2 {};
}
TEST_CASE("features/infos/method") {
registry db;
db(
class_<clazz>{"clazz"}(
method_{"non_const_method", &clazz::non_const_method},
method_{"non_const_method_noexcept", &clazz::non_const_method_noexcept},
method_{"const_method", &clazz::const_method},
method_{"const_method_noexcept", &clazz::const_method_noexcept},
method_{"non_const_method_ref", &clazz::non_const_method_ref},
method_{"non_const_method_noexcept_ref", &clazz::non_const_method_noexcept_ref},
method_{"const_method_ref", &clazz::const_method_ref},
method_{"const_method_noexcept_ref", &clazz::const_method_noexcept_ref},
method_{"non_const_method_rref", &clazz::non_const_method_rref},
method_{"non_const_method_noexcept_rref", &clazz::non_const_method_noexcept_rref},
method_{"const_method_rref", &clazz::const_method_rref},
method_{"const_method_noexcept_rref", &clazz::const_method_noexcept_rref},
//
method_{"non_const_method_volatile", &clazz::non_const_method_volatile},
method_{"non_const_method_noexcept_volatile", &clazz::non_const_method_noexcept_volatile},
method_{"const_method_volatile", &clazz::const_method_volatile},
method_{"const_method_noexcept_volatile", &clazz::const_method_noexcept_volatile},
method_{"non_const_method_ref_volatile", &clazz::non_const_method_ref_volatile},
method_{"non_const_method_noexcept_ref_volatile", &clazz::non_const_method_noexcept_ref_volatile},
method_{"const_method_ref_volatile", &clazz::const_method_ref_volatile},
method_{"const_method_noexcept_ref_volatile", &clazz::const_method_noexcept_ref_volatile},
method_{"non_const_method_rref_volatile", &clazz::non_const_method_rref_volatile},
method_{"non_const_method_noexcept_rref_volatile", &clazz::non_const_method_noexcept_rref_volatile},
method_{"const_method_rref_volatile", &clazz::const_method_rref_volatile},
method_{"const_method_noexcept_rref_volatile", &clazz::const_method_noexcept_rref_volatile}
)
);
SUBCASE("non_const_method") {
const method_info mi = db.get_method_by_path("clazz::non_const_method");
REQUIRE(mi);
const method_info mi2 = db.get_method_by_path("clazz::non_const_method_volatile");
REQUIRE(mi2);
{
CHECK(mi.type().arity() == 0);
CHECK(mi.type().class_type() == type_db::get<clazz>());
CHECK(mi.type().return_type() == type_db::get<int>());
CHECK(mi.type().flags() == method_flags{});
CHECK(mi2.type().arity() == 0);
CHECK(mi2.type().class_type() == type_db::get<clazz>());
CHECK(mi2.type().return_type() == type_db::get<int>());
CHECK(mi2.type().flags() == method_flags::is_volatile);
}
{
CHECK(mi.is_invocable_with<clazz&>());
CHECK_FALSE(mi.is_invocable_with<const clazz&>());
CHECK(mi.is_invocable_with<clazz&&>());
CHECK_FALSE(mi.is_invocable_with<const clazz&&>());
CHECK(mi2.is_invocable_with<clazz&>());
CHECK_FALSE(mi2.is_invocable_with<const clazz&>());
CHECK(mi2.is_invocable_with<clazz&&>());
CHECK_FALSE(mi2.is_invocable_with<const clazz&&>());
}
{
clazz cl;
CHECK(mi.invoke(cl).value() == 1);
CHECK_THROWS(mi.invoke(std::as_const(cl)));
CHECK(mi.invoke(std::move(cl)).value() == 1);
CHECK_THROWS(mi.invoke(std::move(std::as_const(cl))));
CHECK(mi2.invoke(cl).value() == 1);
CHECK_THROWS(mi2.invoke(std::as_const(cl)));
CHECK(mi2.invoke(std::move(cl)).value() == 1);
CHECK_THROWS(mi2.invoke(std::move(std::as_const(cl))));
}
static_assert(std::is_invocable_v<decltype(&clazz::non_const_method), clazz&>);
static_assert(!std::is_invocable_v<decltype(&clazz::non_const_method), const clazz&>);
static_assert(std::is_invocable_v<decltype(&clazz::non_const_method), clazz&&>);
static_assert(!std::is_invocable_v<decltype(&clazz::non_const_method), const clazz&&>);
static_assert(std::is_invocable_v<decltype(&clazz::non_const_method_volatile), clazz&>);
static_assert(!std::is_invocable_v<decltype(&clazz::non_const_method_volatile), const clazz&>);
static_assert(std::is_invocable_v<decltype(&clazz::non_const_method_volatile), clazz&&>);
static_assert(!std::is_invocable_v<decltype(&clazz::non_const_method_volatile), const clazz&&>);
}
SUBCASE("non_const_method_noexcept") {
const method_info mi = db.get_method_by_path("clazz::non_const_method_noexcept");
REQUIRE(mi);
const method_info mi2 = db.get_method_by_path("clazz::non_const_method_noexcept_volatile");
REQUIRE(mi2);
{
CHECK(mi.type().arity() == 0);
CHECK(mi.type().class_type() == type_db::get<clazz>());
CHECK(mi.type().return_type() == type_db::get<int>());
CHECK(mi.type().flags() == method_flags::is_noexcept);
CHECK(mi2.type().arity() == 0);
CHECK(mi2.type().class_type() == type_db::get<clazz>());
CHECK(mi2.type().return_type() == type_db::get<int>());
CHECK(mi2.type().flags() == (method_flags::is_noexcept | method_flags::is_volatile));
}
{
CHECK(mi.is_invocable_with<clazz&>());
CHECK_FALSE(mi.is_invocable_with<const clazz&>());
CHECK(mi.is_invocable_with<clazz&&>());
CHECK_FALSE(mi.is_invocable_with<const clazz&&>());
CHECK(mi2.is_invocable_with<clazz&>());
CHECK_FALSE(mi2.is_invocable_with<const clazz&>());
CHECK(mi2.is_invocable_with<clazz&&>());
CHECK_FALSE(mi2.is_invocable_with<const clazz&&>());
}
{
clazz cl;
CHECK(mi.invoke(cl).value() == 2);
CHECK_THROWS(mi.invoke(std::as_const(cl)));
CHECK(mi.invoke(std::move(cl)).value() == 2);
CHECK_THROWS(mi.invoke(std::move(std::as_const(cl))));
CHECK(mi2.invoke(cl).value() == 2);
CHECK_THROWS(mi2.invoke(std::as_const(cl)));
CHECK(mi2.invoke(std::move(cl)).value() == 2);
CHECK_THROWS(mi2.invoke(std::move(std::as_const(cl))));
}
static_assert(std::is_invocable_v<decltype(&clazz::non_const_method_noexcept), clazz&>);
static_assert(!std::is_invocable_v<decltype(&clazz::non_const_method_noexcept), const clazz&>);
static_assert(std::is_invocable_v<decltype(&clazz::non_const_method_noexcept), clazz&&>);
static_assert(!std::is_invocable_v<decltype(&clazz::non_const_method_noexcept), const clazz&&>);
static_assert(std::is_invocable_v<decltype(&clazz::non_const_method_noexcept_volatile), clazz&>);
static_assert(!std::is_invocable_v<decltype(&clazz::non_const_method_noexcept_volatile), const clazz&>);
static_assert(std::is_invocable_v<decltype(&clazz::non_const_method_noexcept_volatile), clazz&&>);
static_assert(!std::is_invocable_v<decltype(&clazz::non_const_method_noexcept_volatile), const clazz&&>);
}
SUBCASE("const_method") {
const method_info mi = db.get_method_by_path("clazz::const_method");
REQUIRE(mi);
const method_info mi2 = db.get_method_by_path("clazz::const_method_volatile");
REQUIRE(mi2);
{
CHECK(mi.type().arity() == 0);
CHECK(mi.type().class_type() == type_db::get<clazz>());
CHECK(mi.type().return_type() == type_db::get<int>());
CHECK(mi.type().flags() == method_flags::is_const);
CHECK(mi2.type().arity() == 0);
CHECK(mi2.type().class_type() == type_db::get<clazz>());
CHECK(mi2.type().return_type() == type_db::get<int>());
CHECK(mi2.type().flags() == (method_flags::is_const | method_flags::is_volatile));
}
{
CHECK(mi.is_invocable_with<clazz&>());
CHECK(mi.is_invocable_with<const clazz&>());
CHECK(mi.is_invocable_with<clazz&&>());
CHECK(mi.is_invocable_with<const clazz&&>());
CHECK(mi2.is_invocable_with<clazz&>());
CHECK(mi2.is_invocable_with<const clazz&>());
CHECK(mi2.is_invocable_with<clazz&&>());
CHECK(mi2.is_invocable_with<const clazz&&>());
}
{
clazz cl;
CHECK(mi.invoke(cl).value() == 3);
CHECK(mi.invoke(std::as_const(cl)).value() == 3);
CHECK(mi.invoke(std::move(cl)).value() == 3);
CHECK(mi.invoke(std::move(std::as_const(cl))).value() == 3);
CHECK(mi2.invoke(cl).value() == 3);
CHECK(mi2.invoke(std::as_const(cl)).value() == 3);
CHECK(mi2.invoke(std::move(cl)).value() == 3);
CHECK(mi2.invoke(std::move(std::as_const(cl))).value() == 3);
}
static_assert(std::is_invocable_v<decltype(&clazz::const_method), clazz&>);
static_assert(std::is_invocable_v<decltype(&clazz::const_method), const clazz&>);
static_assert(std::is_invocable_v<decltype(&clazz::const_method), clazz&&>);
static_assert(std::is_invocable_v<decltype(&clazz::const_method), const clazz&&>);
static_assert(std::is_invocable_v<decltype(&clazz::const_method_volatile), clazz&>);
static_assert(std::is_invocable_v<decltype(&clazz::const_method_volatile), const clazz&>);
static_assert(std::is_invocable_v<decltype(&clazz::const_method_volatile), clazz&&>);
static_assert(std::is_invocable_v<decltype(&clazz::const_method_volatile), const clazz&&>);
}
SUBCASE("const_method_noexcept") {
const method_info mi = db.get_method_by_path("clazz::const_method_noexcept");
REQUIRE(mi);
const method_info mi2 = db.get_method_by_path("clazz::const_method_noexcept_volatile");
REQUIRE(mi2);
{
CHECK(mi.type().arity() == 0);
CHECK(mi.type().class_type() == type_db::get<clazz>());
CHECK(mi.type().return_type() == type_db::get<int>());
CHECK(mi.type().flags() == (method_flags::is_const | method_flags::is_noexcept));
CHECK(mi2.type().arity() == 0);
CHECK(mi2.type().class_type() == type_db::get<clazz>());
CHECK(mi2.type().return_type() == type_db::get<int>());
CHECK(mi2.type().flags() == (method_flags::is_const | method_flags::is_noexcept | method_flags::is_volatile));
}
{
CHECK(mi.is_invocable_with<clazz&>());
CHECK(mi.is_invocable_with<const clazz&>());
CHECK(mi.is_invocable_with<clazz&&>());
CHECK(mi.is_invocable_with<const clazz&&>());
CHECK(mi2.is_invocable_with<clazz&>());
CHECK(mi2.is_invocable_with<const clazz&>());
CHECK(mi2.is_invocable_with<clazz&&>());
CHECK(mi2.is_invocable_with<const clazz&&>());
}
{
clazz cl;
CHECK(mi.invoke(cl).value() == 4);
CHECK(mi.invoke(std::as_const(cl)).value() == 4);
CHECK(mi.invoke(std::move(cl)).value() == 4);
CHECK(mi.invoke(std::move(std::as_const(cl))).value() == 4);
CHECK(mi2.invoke(cl).value() == 4);
CHECK(mi2.invoke(std::as_const(cl)).value() == 4);
CHECK(mi2.invoke(std::move(cl)).value() == 4);
CHECK(mi2.invoke(std::move(std::as_const(cl))).value() == 4);
}
static_assert(std::is_invocable_v<decltype(&clazz::const_method_noexcept), clazz&>);
static_assert(std::is_invocable_v<decltype(&clazz::const_method_noexcept), const clazz&>);
static_assert(std::is_invocable_v<decltype(&clazz::const_method_noexcept), clazz&&>);
static_assert(std::is_invocable_v<decltype(&clazz::const_method_noexcept), const clazz&&>);
static_assert(std::is_invocable_v<decltype(&clazz::const_method_noexcept_volatile), clazz&>);
static_assert(std::is_invocable_v<decltype(&clazz::const_method_noexcept_volatile), const clazz&>);
static_assert(std::is_invocable_v<decltype(&clazz::const_method_noexcept_volatile), clazz&&>);
static_assert(std::is_invocable_v<decltype(&clazz::const_method_noexcept_volatile), const clazz&&>);
}
SUBCASE("non_const_method_ref") {
const method_info mi = db.get_method_by_path("clazz::non_const_method_ref");
REQUIRE(mi);
const method_info mi2 = db.get_method_by_path("clazz::non_const_method_ref_volatile");
REQUIRE(mi2);
{
CHECK(mi.type().arity() == 0);
CHECK(mi.type().class_type() == type_db::get<clazz>());
CHECK(mi.type().return_type() == type_db::get<int>());
CHECK(mi.type().flags() == method_flags::is_lvalue_qualified);
CHECK(mi2.type().arity() == 0);
CHECK(mi2.type().class_type() == type_db::get<clazz>());
CHECK(mi2.type().return_type() == type_db::get<int>());
CHECK(mi2.type().flags() == (method_flags::is_volatile | method_flags::is_lvalue_qualified));
}
{
CHECK(mi.is_invocable_with<clazz&>());
CHECK_FALSE(mi.is_invocable_with<const clazz&>());
CHECK_FALSE(mi.is_invocable_with<clazz&&>());
CHECK_FALSE(mi.is_invocable_with<const clazz&&>());
CHECK(mi2.is_invocable_with<clazz&>());
CHECK_FALSE(mi2.is_invocable_with<const clazz&>());
CHECK_FALSE(mi2.is_invocable_with<clazz&&>());
CHECK_FALSE(mi2.is_invocable_with<const clazz&&>());
}
{
clazz cl;
CHECK(mi.invoke(cl).value() == 5);
CHECK_THROWS(mi.invoke(std::as_const(cl)));
CHECK_THROWS(mi.invoke(std::move(cl)));
CHECK_THROWS(mi.invoke(std::move(std::as_const(cl))));
CHECK(mi2.invoke(cl).value() == 5);
CHECK_THROWS(mi2.invoke(std::as_const(cl)));
CHECK_THROWS(mi2.invoke(std::move(cl)));
CHECK_THROWS(mi2.invoke(std::move(std::as_const(cl))));
}
static_assert(std::is_invocable_v<decltype(&clazz::non_const_method_ref), clazz&>);
static_assert(!std::is_invocable_v<decltype(&clazz::non_const_method_ref), const clazz&>);
static_assert(!std::is_invocable_v<decltype(&clazz::non_const_method_ref), clazz&&>);
static_assert(!std::is_invocable_v<decltype(&clazz::non_const_method_ref), const clazz&&>);
static_assert(std::is_invocable_v<decltype(&clazz::non_const_method_ref_volatile), clazz&>);
static_assert(!std::is_invocable_v<decltype(&clazz::non_const_method_ref_volatile), const clazz&>);
static_assert(!std::is_invocable_v<decltype(&clazz::non_const_method_ref_volatile), clazz&&>);
static_assert(!std::is_invocable_v<decltype(&clazz::non_const_method_ref_volatile), const clazz&&>);
}
SUBCASE("non_const_method_noexcept_ref") {
const method_info mi = db.get_method_by_path("clazz::non_const_method_noexcept_ref");
REQUIRE(mi);
const method_info mi2 = db.get_method_by_path("clazz::non_const_method_noexcept_ref_volatile");
REQUIRE(mi2);
{
CHECK(mi.type().arity() == 0);
CHECK(mi.type().class_type() == type_db::get<clazz>());
CHECK(mi.type().return_type() == type_db::get<int>());
CHECK(mi.type().flags() == (method_flags::is_noexcept | method_flags::is_lvalue_qualified));
CHECK(mi2.type().arity() == 0);
CHECK(mi2.type().class_type() == type_db::get<clazz>());
CHECK(mi2.type().return_type() == type_db::get<int>());
CHECK(mi2.type().flags() == (method_flags::is_noexcept | method_flags::is_volatile | method_flags::is_lvalue_qualified));
}
{
CHECK(mi.is_invocable_with<clazz&>());
CHECK_FALSE(mi.is_invocable_with<const clazz&>());
CHECK_FALSE(mi.is_invocable_with<clazz&&>());
CHECK_FALSE(mi.is_invocable_with<const clazz&&>());
CHECK(mi2.is_invocable_with<clazz&>());
CHECK_FALSE(mi2.is_invocable_with<const clazz&>());
CHECK_FALSE(mi2.is_invocable_with<clazz&&>());
CHECK_FALSE(mi2.is_invocable_with<const clazz&&>());
}
{
clazz cl;
CHECK(mi.invoke(cl).value() == 6);
CHECK_THROWS(mi.invoke(std::as_const(cl)));
CHECK_THROWS(mi.invoke(std::move(cl)));
CHECK_THROWS(mi.invoke(std::move(std::as_const(cl))));
CHECK(mi2.invoke(cl).value() == 6);
CHECK_THROWS(mi2.invoke(std::as_const(cl)));
CHECK_THROWS(mi2.invoke(std::move(cl)));
CHECK_THROWS(mi2.invoke(std::move(std::as_const(cl))));
}
static_assert(std::is_invocable_v<decltype(&clazz::non_const_method_noexcept_ref), clazz&>);
static_assert(!std::is_invocable_v<decltype(&clazz::non_const_method_noexcept_ref), const clazz&>);
static_assert(!std::is_invocable_v<decltype(&clazz::non_const_method_noexcept_ref), clazz&&>);
static_assert(!std::is_invocable_v<decltype(&clazz::non_const_method_noexcept_ref), const clazz&&>);
static_assert(std::is_invocable_v<decltype(&clazz::non_const_method_noexcept_ref_volatile), clazz&>);
static_assert(!std::is_invocable_v<decltype(&clazz::non_const_method_noexcept_ref_volatile), const clazz&>);
static_assert(!std::is_invocable_v<decltype(&clazz::non_const_method_noexcept_ref_volatile), clazz&&>);
static_assert(!std::is_invocable_v<decltype(&clazz::non_const_method_noexcept_ref_volatile), const clazz&&>);
}
SUBCASE("const_method_ref") {
const method_info mi = db.get_method_by_path("clazz::const_method_ref");
REQUIRE(mi);
const method_info mi2 = db.get_method_by_path("clazz::const_method_ref_volatile");
REQUIRE(mi2);
{
CHECK(mi.type().arity() == 0);
CHECK(mi.type().class_type() == type_db::get<clazz>());
CHECK(mi.type().return_type() == type_db::get<int>());
CHECK(mi.type().flags() == (method_flags::is_const | method_flags::is_lvalue_qualified));
CHECK(mi2.type().arity() == 0);
CHECK(mi2.type().class_type() == type_db::get<clazz>());
CHECK(mi2.type().return_type() == type_db::get<int>());
CHECK(mi2.type().flags() == (method_flags::is_const | method_flags::is_volatile | method_flags::is_lvalue_qualified));
}
{
CHECK(mi.is_invocable_with<clazz&>());
CHECK(mi.is_invocable_with<const clazz&>());
CHECK_FALSE(mi.is_invocable_with<clazz&&>());
CHECK_FALSE(mi.is_invocable_with<const clazz&&>());
CHECK(mi2.is_invocable_with<clazz&>());
CHECK(mi2.is_invocable_with<const clazz&>());
CHECK_FALSE(mi2.is_invocable_with<clazz&&>());
CHECK_FALSE(mi2.is_invocable_with<const clazz&&>());
}
{
clazz cl;
CHECK(mi.invoke(cl).value() == 7);
CHECK(mi.invoke(std::as_const(cl)).value() == 7);
CHECK_THROWS(mi.invoke(std::move(cl)));
CHECK_THROWS(mi.invoke(std::move(std::as_const(cl))));
CHECK(mi2.invoke(cl).value() == 7);
CHECK(mi2.invoke(std::as_const(cl)).value() == 7);
CHECK_THROWS(mi2.invoke(std::move(cl)));
CHECK_THROWS(mi2.invoke(std::move(std::as_const(cl))));
}
static_assert(std::is_invocable_v<decltype(&clazz::const_method_ref), clazz&>);
static_assert(std::is_invocable_v<decltype(&clazz::const_method_ref), const clazz&>);
//static_assert(!std::is_invocable_v<decltype(&clazz::const_method_ref), clazz&&>); // msvc issue
//static_assert(!std::is_invocable_v<decltype(&clazz::const_method_ref), const clazz&&>); // msvc issue
static_assert(std::is_invocable_v<decltype(&clazz::const_method_ref_volatile), clazz&>);
static_assert(std::is_invocable_v<decltype(&clazz::const_method_ref_volatile), const clazz&>);
static_assert(!std::is_invocable_v<decltype(&clazz::const_method_ref_volatile), clazz&&>);
static_assert(!std::is_invocable_v<decltype(&clazz::const_method_ref_volatile), const clazz&&>);
}
SUBCASE("const_method_noexcept_ref") {
const method_info mi = db.get_method_by_path("clazz::const_method_noexcept_ref");
REQUIRE(mi);
const method_info mi2 = db.get_method_by_path("clazz::const_method_noexcept_ref_volatile");
REQUIRE(mi2);
{
CHECK(mi.type().arity() == 0);
CHECK(mi.type().class_type() == type_db::get<clazz>());
CHECK(mi.type().return_type() == type_db::get<int>());
CHECK(mi.type().flags() == (method_flags::is_const | method_flags::is_noexcept | method_flags::is_lvalue_qualified));
CHECK(mi2.type().arity() == 0);
CHECK(mi2.type().class_type() == type_db::get<clazz>());
CHECK(mi2.type().return_type() == type_db::get<int>());
CHECK(mi2.type().flags() == (method_flags::is_const | method_flags::is_noexcept | method_flags::is_volatile | method_flags::is_lvalue_qualified));
}
{
CHECK(mi.is_invocable_with<clazz&>());
CHECK(mi.is_invocable_with<const clazz&>());
CHECK_FALSE(mi.is_invocable_with<clazz&&>());
CHECK_FALSE(mi.is_invocable_with<const clazz&&>());
CHECK(mi2.is_invocable_with<clazz&>());
CHECK(mi2.is_invocable_with<const clazz&>());
CHECK_FALSE(mi2.is_invocable_with<clazz&&>());
CHECK_FALSE(mi2.is_invocable_with<const clazz&&>());
}
{
clazz cl;
CHECK(mi.invoke(cl).value() == 8);
CHECK(mi.invoke(std::as_const(cl)).value() == 8);
CHECK_THROWS(mi.invoke(std::move(cl)));
CHECK_THROWS(mi.invoke(std::move(std::as_const(cl))));
CHECK(mi2.invoke(cl).value() == 8);
CHECK(mi2.invoke(std::as_const(cl)).value() == 8);
CHECK_THROWS(mi2.invoke(std::move(cl)));
CHECK_THROWS(mi2.invoke(std::move(std::as_const(cl))));
}
static_assert(std::is_invocable_v<decltype(&clazz::const_method_noexcept_ref), clazz&>);
static_assert(std::is_invocable_v<decltype(&clazz::const_method_noexcept_ref), const clazz&>);
//static_assert(!std::is_invocable_v<decltype(&clazz::const_method_noexcept_ref), clazz&&>); // msvc issue
//static_assert(!std::is_invocable_v<decltype(&clazz::const_method_noexcept_ref), const clazz&&>); // msvc issue
static_assert(std::is_invocable_v<decltype(&clazz::const_method_noexcept_ref_volatile), clazz&>);
static_assert(std::is_invocable_v<decltype(&clazz::const_method_noexcept_ref_volatile), const clazz&>);
static_assert(!std::is_invocable_v<decltype(&clazz::const_method_noexcept_ref_volatile), clazz&&>);
static_assert(!std::is_invocable_v<decltype(&clazz::const_method_noexcept_ref_volatile), const clazz&&>);
}
SUBCASE("non_const_method_rref") {
const method_info mi = db.get_method_by_path("clazz::non_const_method_rref");
REQUIRE(mi);
const method_info mi2 = db.get_method_by_path("clazz::non_const_method_rref_volatile");
REQUIRE(mi2);
{
CHECK(mi.type().arity() == 0);
CHECK(mi.type().class_type() == type_db::get<clazz>());
CHECK(mi.type().return_type() == type_db::get<int>());
CHECK(mi.type().flags() == method_flags::is_rvalue_qualified);
CHECK(mi2.type().arity() == 0);
CHECK(mi2.type().class_type() == type_db::get<clazz>());
CHECK(mi2.type().return_type() == type_db::get<int>());
CHECK(mi2.type().flags() == (method_flags::is_volatile | method_flags::is_rvalue_qualified));
}
{
CHECK_FALSE(mi.is_invocable_with<clazz&>());
CHECK_FALSE(mi.is_invocable_with<const clazz&>());
CHECK(mi.is_invocable_with<clazz&&>());
CHECK_FALSE(mi.is_invocable_with<const clazz&&>());
CHECK_FALSE(mi2.is_invocable_with<clazz&>());
CHECK_FALSE(mi2.is_invocable_with<const clazz&>());
CHECK(mi2.is_invocable_with<clazz&&>());
CHECK_FALSE(mi2.is_invocable_with<const clazz&&>());
}
{
clazz cl;
CHECK_THROWS(mi.invoke(cl));
CHECK_THROWS(mi.invoke(std::as_const(cl)));
CHECK(mi.invoke(std::move(cl)).value() == 9);
CHECK_THROWS(mi.invoke(std::move(std::as_const(cl))));
CHECK_THROWS(mi2.invoke(cl));
CHECK_THROWS(mi2.invoke(std::as_const(cl)));
CHECK(mi2.invoke(std::move(cl)).value() == 9);
CHECK_THROWS(mi2.invoke(std::move(std::as_const(cl))));
}
static_assert(!std::is_invocable_v<decltype(&clazz::non_const_method_rref), clazz&>);
static_assert(!std::is_invocable_v<decltype(&clazz::non_const_method_rref), const clazz&>);
static_assert(std::is_invocable_v<decltype(&clazz::non_const_method_rref), clazz&&>);
static_assert(!std::is_invocable_v<decltype(&clazz::non_const_method_rref), const clazz&&>);
static_assert(!std::is_invocable_v<decltype(&clazz::non_const_method_rref_volatile), clazz&>);
static_assert(!std::is_invocable_v<decltype(&clazz::non_const_method_rref_volatile), const clazz&>);
static_assert(std::is_invocable_v<decltype(&clazz::non_const_method_rref_volatile), clazz&&>);
static_assert(!std::is_invocable_v<decltype(&clazz::non_const_method_rref_volatile), const clazz&&>);
}
SUBCASE("non_const_method_noexcept_rref") {
const method_info mi = db.get_method_by_path("clazz::non_const_method_noexcept_rref");
REQUIRE(mi);
const method_info mi2 = db.get_method_by_path("clazz::non_const_method_noexcept_rref_volatile");
REQUIRE(mi2);
{
CHECK(mi.type().arity() == 0);
CHECK(mi.type().class_type() == type_db::get<clazz>());
CHECK(mi.type().return_type() == type_db::get<int>());
CHECK(mi.type().flags() == (method_flags::is_noexcept | method_flags::is_rvalue_qualified));
CHECK(mi2.type().arity() == 0);
CHECK(mi2.type().class_type() == type_db::get<clazz>());
CHECK(mi2.type().return_type() == type_db::get<int>());
CHECK(mi2.type().flags() == (method_flags::is_noexcept | method_flags::is_volatile | method_flags::is_rvalue_qualified));
}
{
CHECK_FALSE(mi.is_invocable_with<clazz&>());
CHECK_FALSE(mi.is_invocable_with<const clazz&>());
CHECK(mi.is_invocable_with<clazz&&>());
CHECK_FALSE(mi.is_invocable_with<const clazz&&>());
CHECK_FALSE(mi2.is_invocable_with<clazz&>());
CHECK_FALSE(mi2.is_invocable_with<const clazz&>());
CHECK(mi2.is_invocable_with<clazz&&>());
CHECK_FALSE(mi2.is_invocable_with<const clazz&&>());
}
{
clazz cl;
CHECK_THROWS(mi.invoke(cl));
CHECK_THROWS(mi.invoke(std::as_const(cl)));
CHECK(mi.invoke(std::move(cl)).value() == 10);
CHECK_THROWS(mi.invoke(std::move(std::as_const(cl))));
CHECK_THROWS(mi2.invoke(cl));
CHECK_THROWS(mi2.invoke(std::as_const(cl)));
CHECK(mi2.invoke(std::move(cl)).value() == 10);
CHECK_THROWS(mi2.invoke(std::move(std::as_const(cl))));
}
static_assert(!std::is_invocable_v<decltype(&clazz::non_const_method_noexcept_rref), clazz&>);
static_assert(!std::is_invocable_v<decltype(&clazz::non_const_method_noexcept_rref), const clazz&>);
static_assert(std::is_invocable_v<decltype(&clazz::non_const_method_noexcept_rref), clazz&&>);
static_assert(!std::is_invocable_v<decltype(&clazz::non_const_method_noexcept_rref), const clazz&&>);
static_assert(!std::is_invocable_v<decltype(&clazz::non_const_method_noexcept_rref_volatile), clazz&>);
static_assert(!std::is_invocable_v<decltype(&clazz::non_const_method_noexcept_rref_volatile), const clazz&>);
static_assert(std::is_invocable_v<decltype(&clazz::non_const_method_noexcept_rref_volatile), clazz&&>);
static_assert(!std::is_invocable_v<decltype(&clazz::non_const_method_noexcept_rref_volatile), const clazz&&>);
}
SUBCASE("const_method_rref") {
const method_info mi = db.get_method_by_path("clazz::const_method_rref");
REQUIRE(mi);
const method_info mi2 = db.get_method_by_path("clazz::const_method_rref_volatile");
REQUIRE(mi2);
{
CHECK(mi.type().arity() == 0);
CHECK(mi.type().class_type() == type_db::get<clazz>());
CHECK(mi.type().return_type() == type_db::get<int>());
CHECK(mi.type().flags() == (method_flags::is_const | method_flags::is_rvalue_qualified));
CHECK(mi2.type().arity() == 0);
CHECK(mi2.type().class_type() == type_db::get<clazz>());
CHECK(mi2.type().return_type() == type_db::get<int>());
CHECK(mi2.type().flags() == (method_flags::is_const | method_flags::is_volatile | method_flags::is_rvalue_qualified));
}
{
CHECK_FALSE(mi.is_invocable_with<clazz&>());
CHECK_FALSE(mi.is_invocable_with<const clazz&>());
CHECK(mi.is_invocable_with<clazz&&>());
CHECK(mi.is_invocable_with<const clazz&&>());
CHECK_FALSE(mi2.is_invocable_with<clazz&>());
CHECK_FALSE(mi2.is_invocable_with<const clazz&>());
CHECK(mi2.is_invocable_with<clazz&&>());
CHECK(mi2.is_invocable_with<const clazz&&>());
}
{
clazz cl;
CHECK_THROWS(mi.invoke(cl));
CHECK_THROWS(mi.invoke(std::as_const(cl)));
CHECK(mi.invoke(std::move(cl)).value() == 11);
CHECK(mi.invoke(std::move(std::as_const(cl))).value() == 11);
CHECK_THROWS(mi2.invoke(cl));
CHECK_THROWS(mi2.invoke(std::as_const(cl)));
CHECK(mi2.invoke(std::move(cl)).value() == 11);
CHECK(mi2.invoke(std::move(std::as_const(cl))).value() == 11);
}
static_assert(!std::is_invocable_v<decltype(&clazz::const_method_rref), clazz&>);
static_assert(!std::is_invocable_v<decltype(&clazz::const_method_rref), const clazz&>);
static_assert(std::is_invocable_v<decltype(&clazz::const_method_rref), clazz&&>);
static_assert(std::is_invocable_v<decltype(&clazz::const_method_rref), const clazz&&>);
static_assert(!std::is_invocable_v<decltype(&clazz::const_method_rref_volatile), clazz&>);
static_assert(!std::is_invocable_v<decltype(&clazz::const_method_rref_volatile), const clazz&>);
static_assert(std::is_invocable_v<decltype(&clazz::const_method_rref_volatile), clazz&&>);
static_assert(std::is_invocable_v<decltype(&clazz::const_method_rref_volatile), const clazz&&>);
}
SUBCASE("const_method_noexcept_rref") {
const method_info mi = db.get_method_by_path("clazz::const_method_noexcept_rref");
REQUIRE(mi);
const method_info mi2 = db.get_method_by_path("clazz::const_method_noexcept_rref_volatile");
REQUIRE(mi2);
{
CHECK(mi.type().arity() == 0);
CHECK(mi.type().class_type() == type_db::get<clazz>());
CHECK(mi.type().return_type() == type_db::get<int>());
CHECK(mi.type().flags() == (method_flags::is_const | method_flags::is_noexcept | method_flags::is_rvalue_qualified));
CHECK(mi2.type().arity() == 0);
CHECK(mi2.type().class_type() == type_db::get<clazz>());
CHECK(mi2.type().return_type() == type_db::get<int>());
CHECK(mi2.type().flags() == (method_flags::is_const | method_flags::is_noexcept | method_flags::is_volatile | method_flags::is_rvalue_qualified));
}
{
CHECK_FALSE(mi.is_invocable_with<clazz&>());
CHECK_FALSE(mi.is_invocable_with<const clazz&>());
CHECK(mi.is_invocable_with<clazz&&>());
CHECK(mi.is_invocable_with<const clazz&&>());
CHECK_FALSE(mi2.is_invocable_with<clazz&>());
CHECK_FALSE(mi2.is_invocable_with<const clazz&>());
CHECK(mi2.is_invocable_with<clazz&&>());
CHECK(mi2.is_invocable_with<const clazz&&>());
}
{
clazz cl;
CHECK_THROWS(mi.invoke(cl));
CHECK_THROWS(mi.invoke(std::as_const(cl)));
CHECK(mi.invoke(std::move(cl)).value() == 12);
CHECK(mi.invoke(std::move(std::as_const(cl))).value() == 12);
CHECK_THROWS(mi2.invoke(cl));
CHECK_THROWS(mi2.invoke(std::as_const(cl)));
CHECK(mi2.invoke(std::move(cl)).value() == 12);
CHECK(mi2.invoke(std::move(std::as_const(cl))).value() == 12);
}
static_assert(!std::is_invocable_v<decltype(&clazz::const_method_noexcept_rref), clazz&>);
static_assert(!std::is_invocable_v<decltype(&clazz::const_method_noexcept_rref), const clazz&>);
static_assert(std::is_invocable_v<decltype(&clazz::const_method_noexcept_rref), clazz&&>);
static_assert(std::is_invocable_v<decltype(&clazz::const_method_noexcept_rref), const clazz&&>);
static_assert(!std::is_invocable_v<decltype(&clazz::const_method_noexcept_rref_volatile), clazz&>);
static_assert(!std::is_invocable_v<decltype(&clazz::const_method_noexcept_rref_volatile), const clazz&>);
static_assert(std::is_invocable_v<decltype(&clazz::const_method_noexcept_rref_volatile), clazz&&>);
static_assert(std::is_invocable_v<decltype(&clazz::const_method_noexcept_rref_volatile), const clazz&&>);
}
}

View File

@@ -1,14 +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 "_infos_fwd.hpp"
namespace
{
}
TEST_CASE("features/infos/namespace") {
}

View File

@@ -1,9 +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)
******************************************************************************/
#pragma once
#include "../../meta_tests.hpp"

View File

@@ -1,70 +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 "_registry_fwd.hpp"
namespace
{
using namespace meta_hpp;
using namespace std::string_literals;
}
namespace
{
struct ivec2 {
int x{};
int y{};
[[maybe_unused]] ivec2() = default;
[[maybe_unused]] explicit ivec2(int v): x{v}, y{v} {}
[[maybe_unused]] ivec2(int x, int y): x{x}, y{y} {}
};
}
TEST_CASE("features/registry/registry") {
auto db = registry{}(
namespace_{"vmath"}(data_{"info", "vmath namespace"},
class_<ivec2>{"ivec2"}(data_{"info", "ivec2 class"},
ctor_<>{},
ctor_<int>{},
ctor_<int, int>{},
member_{"x", &ivec2::x}(data_{"info", "x-coord"}),
member_{"y", &ivec2::y}(data_{"info", "y-coord"})
)
)
);
{
const namespace_info vmath_info = db.get_namespace_by_path("vmath");
REQUIRE(vmath_info);
CHECK(vmath_info.name() == "vmath");
CHECK(vmath_info.get_data_by_name("info"));
const class_info ivec2_info = vmath_info.get_class_by_name("ivec2");
REQUIRE(ivec2_info);
CHECK(ivec2_info.name() == "ivec2");
CHECK(ivec2_info.get_data_by_name("info"));
const member_info ivec2_x_info = ivec2_info.get_member_by_name("x");
REQUIRE(ivec2_x_info);
CHECK(ivec2_x_info.name() == "x");
CHECK(ivec2_x_info.get_data_by_name("info"));
}
{
const class_info ivec2_info = db.get_class_by_path("vmath::ivec2");
REQUIRE(ivec2_info);
CHECK(ivec2_info.name() == "ivec2");
const member_info ivec2_x_info = db.get_member_by_path("vmath::ivec2::x");
REQUIRE(ivec2_x_info);
CHECK(ivec2_x_info.name() == "x");
const data_info ivec2_x_data_info = db.get_data_by_path("vmath::ivec2::x::info");
REQUIRE(ivec2_x_data_info);
CHECK(ivec2_x_data_info.name() == "info");
}
}

View File

@@ -1,9 +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)
******************************************************************************/
#pragma once
#include "../../meta_tests.hpp"

View File

@@ -1,83 +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 "_types_fwd.hpp"
namespace
{
using namespace meta_hpp;
using namespace std::string_literals;
}
TEST_CASE("features/types/arithmetic") {
SUBCASE("int") {
using type = int;
REQUIRE(type_db::get<type>());
REQUIRE(type_db::get<type>().is<arithmetic_type>());
const arithmetic_type at = type_db::get<type>().as<arithmetic_type>();
CHECK_FALSE(at.raw_type());
CHECK(at.size() == sizeof(type));
CHECK(at.flags() == (
arithmetic_flags::is_signed |
arithmetic_flags::is_integral));
CHECK_FALSE(at.is_const());
CHECK(at.is_signed());
CHECK_FALSE(at.is_unsigned());
CHECK(at.is_integral());
CHECK_FALSE(at.is_floating_point());
}
SUBCASE("const float") {
using type = const float;
REQUIRE(type_db::get<type>());
REQUIRE(type_db::get<type>().is<arithmetic_type>());
const arithmetic_type at = type_db::get<type>().as<arithmetic_type>();
CHECK(at.raw_type() == type_db::get<float>());
CHECK(at.size() == sizeof(type));
CHECK(at.flags() == (
arithmetic_flags::is_const |
arithmetic_flags::is_signed |
arithmetic_flags::is_floating_point));
CHECK(at.is_const());
CHECK(at.is_signed());
CHECK_FALSE(at.is_unsigned());
CHECK_FALSE(at.is_integral());
CHECK(at.is_floating_point());
}
SUBCASE("const unsigned") {
using type = const unsigned;
REQUIRE(type_db::get<type>());
REQUIRE(type_db::get<type>().is<arithmetic_type>());
const arithmetic_type at = type_db::get<type>().as<arithmetic_type>();
CHECK(at.raw_type() == type_db::get<unsigned>());
CHECK(at.size() == sizeof(type));
CHECK(at.flags() == (
arithmetic_flags::is_const |
arithmetic_flags::is_unsigned |
arithmetic_flags::is_integral));
CHECK(at.is_const());
CHECK_FALSE(at.is_signed());
CHECK(at.is_unsigned());
CHECK(at.is_integral());
CHECK_FALSE(at.is_floating_point());
}
}

View File

@@ -1,83 +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 "_types_fwd.hpp"
namespace
{
using namespace meta_hpp;
using namespace std::string_literals;
}
TEST_CASE("features/types/array") {
SUBCASE("int[]") {
using type = int[];
REQUIRE(type_db::get<type>());
REQUIRE(type_db::get<type>().is<array_type>());
const array_type at = type_db::get<type>().as<array_type>();
CHECK(at.data_type() == type_db::get<int>());
CHECK(at.extent() == 0);
CHECK(at.flags() == (array_flags::is_unbounded));
CHECK_FALSE(at.is_bounded());
CHECK(at.is_unbounded());
}
SUBCASE("unsigned[42][]") {
using type = unsigned[][42];
REQUIRE(type_db::get<type>());
REQUIRE(type_db::get<type>().is<array_type>());
const array_type at = type_db::get<type>().as<array_type>();
CHECK(at.data_type() == type_db::get<unsigned[42]>());
CHECK(at.extent() == 0);
CHECK(at.flags() == (array_flags::is_unbounded));
CHECK_FALSE(at.is_bounded());
CHECK(at.is_unbounded());
}
SUBCASE("const int[42][21]") {
using type = const int[42][21];
REQUIRE(type_db::get<type>());
REQUIRE(type_db::get<type>().is<array_type>());
const array_type at = type_db::get<type>().as<array_type>();
CHECK(at.data_type() == type_db::get<const int[21]>());
CHECK(at.extent() == 42);
CHECK(at.flags() == (array_flags::is_bounded));
CHECK(at.is_bounded());
CHECK_FALSE(at.is_unbounded());
}
SUBCASE("const unsigned[42]") {
using type = const unsigned[42];
REQUIRE(type_db::get<type>());
REQUIRE(type_db::get<type>().is<array_type>());
const array_type at = type_db::get<type>().as<array_type>();
CHECK(at.data_type() == type_db::get<const unsigned>());
CHECK(at.extent() == 42);
CHECK(at.flags() == (array_flags::is_bounded));
CHECK(at.is_bounded());
CHECK_FALSE(at.is_unbounded());
}
}

View File

@@ -1,30 +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 "_types_fwd.hpp"
namespace
{
using namespace meta_hpp;
using namespace std::string_literals;
}
namespace
{
struct base {
virtual ~base() = 0;
};
struct derived final : base {
};
}
TEST_CASE("features/types/base") {
base_type bt{typename_arg<base>, typename_arg<derived>};
CHECK(bt.base_class_type() == type_db::get<base>());
CHECK(bt.derived_class_type() == type_db::get<derived>());
}

View File

@@ -1,143 +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 "_types_fwd.hpp"
namespace
{
using namespace meta_hpp;
using namespace std::string_literals;
}
namespace
{
struct base {
virtual ~base() = 0;
};
struct derived final : base {
};
struct empty final {
};
struct ivec2 final {
int x{};
int y{};
};
}
TEST_CASE("features/types/class") {
SUBCASE("base") {
using type = base;
REQUIRE(type_db::get<type>());
REQUIRE(type_db::get<type>().is<class_type>());
const class_type ct = type_db::get<type>().as<class_type>();
CHECK_FALSE(ct.raw_type());
CHECK(ct.size() == sizeof(type));
CHECK(ct.flags() == (
class_flags::is_abstract |
class_flags::is_polymorphic));
CHECK_FALSE(ct.is_const());
CHECK_FALSE(ct.is_empty());
CHECK_FALSE(ct.is_final());
CHECK(ct.is_abstract());
CHECK(ct.is_polymorphic());
}
SUBCASE("derived") {
using type = derived;
REQUIRE(type_db::get<type>());
REQUIRE(type_db::get<type>().is<class_type>());
const class_type ct = type_db::get<type>().as<class_type>();
CHECK_FALSE(ct.raw_type());
CHECK(ct.size() == sizeof(type));
CHECK(ct.flags() == (
class_flags::is_final |
class_flags::is_polymorphic));
CHECK_FALSE(ct.is_const());
CHECK_FALSE(ct.is_empty());
CHECK(ct.is_final());
CHECK_FALSE(ct.is_abstract());
CHECK(ct.is_polymorphic());
}
SUBCASE("empty") {
using type = empty;
REQUIRE(type_db::get<type>());
REQUIRE(type_db::get<type>().is<class_type>());
const class_type ct = type_db::get<type>().as<class_type>();
CHECK_FALSE(ct.raw_type());
CHECK(ct.size() == sizeof(type));
CHECK(ct.flags() == (
class_flags::is_empty |
class_flags::is_final));
CHECK_FALSE(ct.is_const());
CHECK(ct.is_empty());
CHECK(ct.is_final());
CHECK_FALSE(ct.is_abstract());
CHECK_FALSE(ct.is_polymorphic());
}
SUBCASE("ivec2") {
using type = ivec2;
REQUIRE(type_db::get<type>());
REQUIRE(type_db::get<type>().is<class_type>());
const class_type ct = type_db::get<type>().as<class_type>();
CHECK_FALSE(ct.raw_type());
CHECK(ct.size() == sizeof(type));
CHECK(ct.flags() == (
class_flags::is_final));
CHECK_FALSE(ct.is_const());
CHECK_FALSE(ct.is_empty());
CHECK(ct.is_final());
CHECK_FALSE(ct.is_abstract());
CHECK_FALSE(ct.is_polymorphic());
}
SUBCASE("const ivec2") {
using type = const ivec2;
REQUIRE(type_db::get<type>());
REQUIRE(type_db::get<type>().is<class_type>());
const class_type ct = type_db::get<type>().as<class_type>();
REQUIRE(ct.raw_type());
CHECK(ct.raw_type() == type_db::get<ivec2>());
CHECK(ct.size() == sizeof(type));
CHECK(ct.flags() == (
class_flags::is_const |
class_flags::is_final));
CHECK(ct.is_const());
CHECK_FALSE(ct.is_empty());
CHECK(ct.is_final());
CHECK_FALSE(ct.is_abstract());
CHECK_FALSE(ct.is_polymorphic());
}
}

View File

@@ -1,90 +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 "_types_fwd.hpp"
namespace
{
using namespace meta_hpp;
using namespace std::string_literals;
}
namespace
{
struct ivec2 final {
int x{};
int y{};
[[maybe_unused]] ivec2() = default;
[[maybe_unused]] explicit ivec2(int v): x{v}, y{v} {}
[[maybe_unused]] ivec2(int x, int y): x{x}, y{y} {}
};
}
TEST_CASE("features/types/ctor") {
SUBCASE("ivec2_void") {
ctor_type ct{typename_arg<ivec2>, typename_arg<>};
CHECK(ct.class_type() == type_db::get<ivec2>());
CHECK(ct.argument_types().size() == 0);
CHECK(ct.arity() == 0);
CHECK(ct.flags() == (ctor_flags::is_noexcept));
CHECK(ct.is_noexcept());
{
CHECK_FALSE(ct.argument_type(0));
}
}
SUBCASE("ivec2_int") {
ctor_type ct{typename_arg<ivec2>, typename_arg<int>};
CHECK(ct.arity() == 1);
CHECK(ct.class_type() == type_db::get<ivec2>());
CHECK(ct.argument_types().size() == 1);
CHECK(ct.flags() == (ctor_flags{}));
CHECK_FALSE(ct.is_noexcept());
{
REQUIRE(ct.argument_type(0));
const any_type arg0 = ct.argument_type(0);
CHECK(arg0 == type_db::get<int>());
}
{
CHECK_FALSE(ct.argument_type(1));
}
}
SUBCASE("ivec2_int_int") {
ctor_type ct{typename_arg<ivec2>, typename_arg<int, int>};
CHECK(ct.class_type() == type_db::get<ivec2>());
CHECK(ct.argument_types().size() == 2);
CHECK(ct.arity() == 2);
CHECK(ct.flags() == (ctor_flags{}));
CHECK_FALSE(ct.is_noexcept());
{
REQUIRE(ct.argument_type(0));
const any_type arg0 = ct.argument_type(0);
CHECK(arg0 == type_db::get<int>());
}
{
REQUIRE(ct.argument_type(1));
const any_type arg1 = ct.argument_type(1);
CHECK(arg1 == type_db::get<int>());
}
{
CHECK_FALSE(ct.argument_type(2));
}
}
}

View File

@@ -1,57 +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 "_types_fwd.hpp"
namespace
{
using namespace meta_hpp;
using namespace std::string_literals;
}
namespace
{
enum class ecolor : unsigned {
red = 0xFF0000,
green = 0x00FF00,
blue = 0x0000FF,
};
}
TEST_CASE("features/types/enum") {
SUBCASE("ecolor") {
using type = ecolor;
REQUIRE(type_db::get<type>());
REQUIRE(type_db::get<type>().is<enum_type>());
const enum_type et = type_db::get<type>().as<enum_type>();
CHECK(et.size() == sizeof(type));
CHECK_FALSE(et.raw_type());
CHECK(et.underlying_type() == type_db::get<unsigned>());
CHECK(et.flags() == (enum_flags{}));
CHECK_FALSE(et.is_const());
}
SUBCASE("const ecolor") {
using type = const ecolor;
REQUIRE(type_db::get<type>());
REQUIRE(type_db::get<type>().is<enum_type>());
const enum_type et = type_db::get<type>().as<enum_type>();
CHECK(et.size() == sizeof(type));
REQUIRE(et.raw_type());
CHECK(et.raw_type() == type_db::get<ecolor>());
CHECK(et.underlying_type() == type_db::get<unsigned>());
CHECK(et.flags() == (enum_flags::is_const));
CHECK(et.is_const());
}
}

View File

@@ -1,102 +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 "_types_fwd.hpp"
namespace
{
using namespace meta_hpp;
using namespace std::string_literals;
}
namespace
{
struct ivec2 {
int x{};
int y{};
};
[[maybe_unused]] void arg_copy(ivec2) {}
[[maybe_unused]] void arg_ref_noexcept(ivec2&) noexcept {}
[[maybe_unused]] void arg_cref_noexcept(const ivec2&) noexcept {}
}
TEST_CASE("features/types/function") {
SUBCASE("arg_copy") {
using type = decltype(&arg_copy);
REQUIRE(type_db::get<type>());
REQUIRE(type_db::get<type>().is<function_type>());
const function_type ft = type_db::get<type>().as<function_type>();
CHECK(ft.return_type() == type_db::get<void>());
CHECK(ft.argument_types().size() == 1);
CHECK(ft.arity() == 1);
CHECK(ft.flags() == (function_flags{}));
CHECK_FALSE(ft.is_noexcept());
{
REQUIRE(ft.argument_type(0));
const any_type arg0 = ft.argument_type(0);
CHECK(arg0 == type_db::get<ivec2>());
}
{
CHECK_FALSE(ft.argument_type(1));
}
}
SUBCASE("arg_ref_noexcept") {
using type = decltype(&arg_ref_noexcept);
REQUIRE(type_db::get<type>());
REQUIRE(type_db::get<type>().is<function_type>());
const function_type ft = type_db::get<type>().as<function_type>();
CHECK(ft.return_type() == type_db::get<void>());
CHECK(ft.argument_types().size() == 1);
CHECK(ft.arity() == 1);
CHECK(ft.flags() == (function_flags::is_noexcept));
CHECK(ft.is_noexcept());
{
REQUIRE(ft.argument_type(0));
const any_type arg0 = ft.argument_type(0);
CHECK(arg0 == type_db::get<ivec2&>());
}
{
CHECK_FALSE(ft.argument_type(1));
}
}
SUBCASE("arg_cref_noexcept") {
using type = decltype(&arg_cref_noexcept);
REQUIRE(type_db::get<type>());
REQUIRE(type_db::get<type>().is<function_type>());
const function_type ft = type_db::get<type>().as<function_type>();
CHECK(ft.return_type() == type_db::get<void>());
CHECK(ft.argument_types().size() == 1);
CHECK(ft.arity() == 1);
CHECK(ft.flags() == (function_flags::is_noexcept));
CHECK(ft.is_noexcept());
{
REQUIRE(ft.argument_type(0));
const any_type arg0 = ft.argument_type(0);
CHECK(arg0 == type_db::get<const ivec2&>());
}
{
CHECK_FALSE(ft.argument_type(1));
}
}
}

View File

@@ -1,45 +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 "_types_fwd.hpp"
namespace
{
using namespace meta_hpp;
using namespace std::string_literals;
}
namespace
{
struct clazz {
int int_member{};
const int const_int_member{10};
};
}
TEST_CASE("features/types/member") {
SUBCASE("clazz::int_member") {
using type = decltype(&clazz::int_member);
REQUIRE(type_db::get<type>());
REQUIRE(type_db::get<type>().is<member_type>());
const member_type mt = type_db::get<type>().as<member_type>();
CHECK(mt.class_type() == type_db::get<clazz>());
CHECK(mt.value_type() == type_db::get<int>());
}
SUBCASE("clazz::const_int_member") {
using type = decltype(&clazz::const_int_member);
REQUIRE(type_db::get<type>());
REQUIRE(type_db::get<type>().is<member_type>());
const member_type mt = type_db::get<type>().as<member_type>();
CHECK(mt.class_type() == type_db::get<clazz>());
CHECK(mt.value_type() == type_db::get<const int>());
}
}

View File

@@ -1,87 +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 "_types_fwd.hpp"
namespace
{
using namespace meta_hpp;
using namespace std::string_literals;
}
namespace
{
struct ivec2 {
int x{};
int y{};
[[maybe_unused]] int& at(std::size_t i) {
switch ( i ) {
case 0: return x;
case 1: return y;
default: throw std::out_of_range("ivec2::at");
}
}
[[maybe_unused]] int length2() const noexcept {
return x * x + y * y;
}
};
}
TEST_CASE("features/types/method") {
SUBCASE("ivec2::at") {
using type = decltype(&ivec2::at);
REQUIRE(type_db::get<type>());
REQUIRE(type_db::get<type>().is<method_type>());
const method_type mt = type_db::get<type>().as<method_type>();
CHECK(mt.class_type() == type_db::get<ivec2>());
CHECK(mt.return_type() == type_db::get<int&>());
CHECK(mt.argument_types().size() == 1);
CHECK(mt.arity() == 1);
CHECK(mt.flags() == (method_flags{}));
CHECK_FALSE(mt.is_const());
CHECK_FALSE(mt.is_noexcept());
{
REQUIRE(mt.argument_type(0));
const any_type arg0 = mt.argument_type(0);
CHECK(arg0 == type_db::get<std::size_t>());
}
{
CHECK_FALSE(mt.argument_type(1));
}
}
SUBCASE("ivec2::length2") {
using type = decltype(&ivec2::length2);
REQUIRE(type_db::get<type>());
REQUIRE(type_db::get<type>().is<method_type>());
const method_type mt = type_db::get<type>().as<method_type>();
CHECK(mt.class_type() == type_db::get<ivec2>());
CHECK(mt.return_type() == type_db::get<int>());
CHECK(mt.argument_types().size() == 0);
CHECK(mt.arity() == 0);
CHECK(mt.flags() == (
method_flags::is_const |
method_flags::is_noexcept));
CHECK(mt.is_const());
CHECK(mt.is_noexcept());
{
CHECK_FALSE(mt.argument_type(0));
}
}
}

View File

@@ -1,79 +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 "_types_fwd.hpp"
namespace
{
using namespace meta_hpp;
using namespace std::string_literals;
}
namespace
{
struct ivec2 {
int x{};
int y{};
};
}
TEST_CASE("features/types/pointer") {
SUBCASE("ivec2*") {
using type = ivec2*;
REQUIRE(type_db::get<type>());
REQUIRE(type_db::get<type>().is<pointer_type>());
const pointer_type pt = type_db::get<type>().as<pointer_type>();
CHECK(pt.data_type() == type_db::get<ivec2>());
CHECK(pt.flags() == (pointer_flags{}));
CHECK_FALSE(pt.is_const());
}
SUBCASE("const ivec2*") {
using type = const ivec2*;
REQUIRE(type_db::get<type>());
REQUIRE(type_db::get<type>().is<pointer_type>());
const pointer_type pt = type_db::get<type>().as<pointer_type>();
CHECK(pt.data_type() == type_db::get<const ivec2>());
CHECK(pt.flags() == (pointer_flags{}));
CHECK_FALSE(pt.is_const());
}
SUBCASE("ivec2* const") {
using type = ivec2* const;
REQUIRE(type_db::get<type>());
REQUIRE(type_db::get<type>().is<pointer_type>());
const pointer_type pt = type_db::get<type>().as<pointer_type>();
CHECK(pt.data_type() == type_db::get<ivec2>());
CHECK(pt.flags() == (pointer_flags::is_const));
CHECK(pt.is_const());
}
SUBCASE("const ivec2* const") {
using type = const ivec2* const;
REQUIRE(type_db::get<type>());
REQUIRE(type_db::get<type>().is<pointer_type>());
const pointer_type pt = type_db::get<type>().as<pointer_type>();
CHECK(pt.data_type() == type_db::get<const ivec2>());
CHECK(pt.flags() == (pointer_flags::is_const));
CHECK(pt.is_const());
}
}

View File

@@ -1,51 +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 "_types_fwd.hpp"
namespace
{
using namespace meta_hpp;
using namespace std::string_literals;
}
namespace
{
struct ivec2 {
int x{};
int y{};
};
}
TEST_CASE("features/types/reference") {
SUBCASE("ivec2&") {
REQUIRE(type_db::get<ivec2&>());
REQUIRE(type_db::get<ivec2&>().is<reference_type>());
const reference_type rt = type_db::get<ivec2&>().as<reference_type>();
CHECK(rt.data_type() == type_db::get<ivec2>());
CHECK(rt.flags() == (reference_flags::is_lvalue));
CHECK(rt.is_lvalue());
CHECK_FALSE(rt.is_rvalue());
}
SUBCASE("const ivec2&&") {
REQUIRE(type_db::get<const ivec2&&>());
REQUIRE(type_db::get<const ivec2&&>().is<reference_type>());
const reference_type rt = type_db::get<const ivec2&&>().as<reference_type>();
CHECK(rt.data_type() == type_db::get<const ivec2>());
CHECK(rt.flags() == (reference_flags::is_rvalue));
CHECK_FALSE(rt.is_lvalue());
CHECK(rt.is_rvalue());
}
}

View File

@@ -1,44 +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 "_types_fwd.hpp"
namespace
{
using namespace meta_hpp;
using namespace std::string_literals;
}
TEST_CASE("features/types/void") {
SUBCASE("void") {
using type = void;
REQUIRE(type_db::get<type>());
REQUIRE(type_db::get<type>().is<void_type>());
const void_type vt = type_db::get<type>().as<void_type>();
CHECK_FALSE(vt.raw_type());
CHECK(vt.flags() == (void_flags{}));
CHECK_FALSE(vt.is_const());
}
SUBCASE("const void") {
using type = const void;
REQUIRE(type_db::get<type>());
REQUIRE(type_db::get<type>().is<void_type>());
const void_type vt = type_db::get<type>().as<void_type>();
REQUIRE(vt.raw_type());
CHECK(vt.raw_type() == type_db::get<void>());
CHECK(vt.flags() == (void_flags::is_const));
CHECK(vt.is_const());
}
}

View File

@@ -1,9 +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)
******************************************************************************/
#pragma once
#include "../../meta_tests.hpp"

File diff suppressed because it is too large Load Diff

View File

@@ -1,76 +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 "_utilities_fwd.hpp"
namespace
{
using namespace meta_hpp;
using namespace std::string_literals;
}
namespace
{
struct ivec2 {
int x{};
int y{};
[[maybe_unused]] ivec2() = default;
[[maybe_unused]] explicit ivec2(int v): x{v}, y{v} {}
[[maybe_unused]] ivec2(int x, int y): x{x}, y{y} {}
[[maybe_unused]] ivec2(ivec2&& other) noexcept {
x = other.x;
y = other.y;
other.x = 0;
other.y = 0;
}
[[maybe_unused]] ivec2(const ivec2& other) noexcept {
x = other.x;
y = other.y;
}
ivec2& operator=(ivec2&&) = delete;
ivec2& operator=(const ivec2&) = delete;
};
}
TEST_CASE("features/utilities/inst/type") {
SUBCASE("ref") {
ivec2 v{1,2};
ivec2& vr = v;
inst a{vr};
CHECK(a.raw_type() == type_db::get<ivec2>());
CHECK(a.ref_type() == inst::ref_types::ref);
}
SUBCASE("cref") {
const ivec2 v{1,2};
const ivec2& vr = v;
inst a{vr};
CHECK(a.raw_type() == type_db::get<ivec2>());
CHECK(a.ref_type() == inst::ref_types::cref);
}
SUBCASE("rref") {
ivec2 v{1,2};
inst a{std::move(v)};
CHECK(a.raw_type() == type_db::get<ivec2>());
CHECK(a.ref_type() == inst::ref_types::rref);
}
SUBCASE("crref") {
const ivec2 v{1,2};
inst a{std::move(v)};
CHECK(a.raw_type() == type_db::get<ivec2>());
CHECK(a.ref_type() == inst::ref_types::crref);
}
}

View File

@@ -1,299 +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 "_utilities_fwd.hpp"
namespace
{
using namespace meta_hpp;
using namespace std::string_literals;
}
namespace
{
struct ivec2 {
int x{};
int y{};
[[maybe_unused]] ivec2() = default;
[[maybe_unused]] explicit ivec2(int v): x{v}, y{v} {}
[[maybe_unused]] ivec2(int x, int y): x{x}, y{y} {}
ivec2(ivec2&& other) noexcept
: x{other.x}
, y{other.y} {
other.x = 0;
other.y = 0;
++move_ctor_counter;
}
ivec2(const ivec2& other) noexcept
: x{other.x}
, y{other.y} {
++copy_ctor_counter;
}
ivec2& operator=(ivec2&& other) = delete;
ivec2& operator=(const ivec2& other) = delete;
public:
static int move_ctor_counter;
static int copy_ctor_counter;
};
int ivec2::move_ctor_counter{0};
int ivec2::copy_ctor_counter{0};
bool operator==(const ivec2& l, const ivec2& r) noexcept {
return l.x == r.x && l.y == r.y;
}
}
TEST_CASE("features/utilities/value") {
ivec2::move_ctor_counter = 0;
ivec2::copy_ctor_counter = 0;
SUBCASE("cast types") {
static_assert(std::is_same_v<
decltype(std::declval<value&>().cast<ivec2>()),
ivec2&>);
static_assert(std::is_same_v<
decltype(std::declval<value&&>().cast<ivec2>()),
ivec2&&>);
static_assert(std::is_same_v<
decltype(std::declval<const value&>().cast<ivec2>()),
const ivec2&>);
static_assert(std::is_same_v<
decltype(std::declval<const value&&>().cast<ivec2>()),
const ivec2&&>);
}
SUBCASE("try_cast types") {
static_assert(std::is_same_v<
decltype(std::declval<value>().try_cast<ivec2>()),
ivec2*>);
static_assert(std::is_same_v<
decltype(std::declval<const value>().try_cast<ivec2>()),
const ivec2*>);
}
SUBCASE("ivec2&") {
ivec2 v{1,2};
ivec2& vr = v;
value val{vr};
CHECK(ivec2::move_ctor_counter == 0);
CHECK(ivec2::copy_ctor_counter == 1);
CHECK(val.type() == type_db::get<ivec2>());
CHECK(!std::memcmp(val.data(), &vr, sizeof(ivec2)));
CHECK(!std::memcmp(val.cdata(), &vr, sizeof(ivec2)));
CHECK(!std::memcmp(std::as_const(val).data(), &vr, sizeof(ivec2)));
CHECK(!std::memcmp(std::as_const(val).cdata(), &vr, sizeof(ivec2)));
CHECK(val == ivec2{1,2});
CHECK(val == value{ivec2{1,2}});
CHECK(val.cast<ivec2>() == ivec2{1,2});
CHECK(std::as_const(val).cast<ivec2>() == ivec2{1,2});
CHECK(*val.try_cast<ivec2>() == ivec2{1,2});
CHECK(*std::as_const(val).try_cast<ivec2>() == ivec2{1,2});
}
SUBCASE("const ivec2&") {
const ivec2 v{1,2};
const ivec2& vr = v;
value val{vr};
CHECK(ivec2::move_ctor_counter == 0);
CHECK(ivec2::copy_ctor_counter == 1);
CHECK(val.type() == type_db::get<ivec2>());
CHECK(!std::memcmp(val.data(), &vr, sizeof(ivec2)));
CHECK(!std::memcmp(val.cdata(), &vr, sizeof(ivec2)));
CHECK(!std::memcmp(std::as_const(val).data(), &vr, sizeof(ivec2)));
CHECK(!std::memcmp(std::as_const(val).cdata(), &vr, sizeof(ivec2)));
CHECK(val == ivec2{1,2});
CHECK(val == value{ivec2{1,2}});
CHECK(val.cast<ivec2>() == ivec2{1,2});
CHECK(std::as_const(val).cast<ivec2>() == ivec2{1,2});
CHECK(*val.try_cast<ivec2>() == ivec2{1,2});
CHECK(*std::as_const(val).try_cast<ivec2>() == ivec2{1,2});
}
SUBCASE("ivec2&&") {
ivec2 v{1,2};
value val{std::move(v)};
CHECK(ivec2::move_ctor_counter == 1);
CHECK(ivec2::copy_ctor_counter == 0);
CHECK(val.type() == type_db::get<ivec2>());
CHECK(val == ivec2{1,2});
CHECK(val == value{ivec2{1,2}});
CHECK(val.cast<ivec2>() == ivec2{1,2});
CHECK(std::as_const(val).cast<ivec2>() == ivec2{1,2});
CHECK(*val.try_cast<ivec2>() == ivec2{1,2});
CHECK(*std::as_const(val).try_cast<ivec2>() == ivec2{1,2});
}
SUBCASE("const ivec2&&") {
const ivec2 v{1,2};
value val{std::move(v)};
CHECK(ivec2::move_ctor_counter == 0);
CHECK(ivec2::copy_ctor_counter == 1);
CHECK(val.type() == type_db::get<ivec2>());
CHECK(val == ivec2{1,2});
CHECK(val == value{ivec2{1,2}});
CHECK(val.cast<ivec2>() == ivec2{1,2});
CHECK(std::as_const(val).cast<ivec2>() == ivec2{1,2});
CHECK(*val.try_cast<ivec2>() == ivec2{1,2});
CHECK(*std::as_const(val).try_cast<ivec2>() == ivec2{1,2});
}
SUBCASE("value(value&&)") {
ivec2 v{1,2};
value val_src{std::move(v)};
CHECK(ivec2::move_ctor_counter == 1);
CHECK(ivec2::copy_ctor_counter == 0);
value val_dst{std::move(val_src)};
CHECK(val_dst == ivec2{1,2});
CHECK(ivec2::move_ctor_counter == 2);
CHECK(ivec2::copy_ctor_counter == 0);
CHECK(val_src == ivec2{0,0});
CHECK(val_src.data() != val_dst.data());
}
SUBCASE("value(const value&)") {
const ivec2 v{1,2};
value val_src{v};
CHECK(ivec2::move_ctor_counter == 0);
CHECK(ivec2::copy_ctor_counter == 1);
value val_dst{val_src};
CHECK(val_dst == ivec2{1,2});
CHECK(ivec2::move_ctor_counter == 0);
CHECK(ivec2::copy_ctor_counter == 2);
CHECK(val_src == ivec2{1,2});
CHECK(val_src.data() != val_dst.data());
}
SUBCASE("value& operator=(value&&)") {
value val_src1{"world"s};
value val_src2{ivec2{1,2}};
CHECK(ivec2::move_ctor_counter == 1);
CHECK(ivec2::copy_ctor_counter == 0);
value val_dst{"hello"s};
val_dst = std::move(val_src1);
CHECK(val_dst == "world"s);
CHECK(ivec2::move_ctor_counter == 1);
CHECK(ivec2::copy_ctor_counter == 0);
val_dst = std::move(val_src2);
CHECK(val_dst == ivec2{1,2});
CHECK(ivec2::move_ctor_counter == 2);
CHECK(ivec2::copy_ctor_counter == 0);
CHECK(val_src2 == ivec2{0,0});
CHECK(val_src2.data() != val_dst.data());
}
SUBCASE("value& operator=(const value&)") {
value val_src1{"world"s};
value val_src2{ivec2{1,2}};
CHECK(ivec2::move_ctor_counter == 1);
CHECK(ivec2::copy_ctor_counter == 0);
value val_dst{"hello"s};
val_dst = val_src1;
CHECK(val_dst == "world"s);
CHECK(ivec2::move_ctor_counter == 1);
CHECK(ivec2::copy_ctor_counter == 0);
val_dst = val_src2;
CHECK(val_dst == ivec2{1,2});
CHECK(ivec2::move_ctor_counter == 1);
CHECK(ivec2::copy_ctor_counter == 1);
CHECK(val_src2 == ivec2{1,2});
CHECK(val_src2.data() != val_dst.data());
}
SUBCASE("swap") {
value val1{"world"s};
value val2{ivec2{1,2}};
CHECK(ivec2::move_ctor_counter == 1);
CHECK(ivec2::copy_ctor_counter == 0);
val1.swap(val2);
CHECK(val1 == ivec2{1,2});
CHECK(val2 == "world"s);
CHECK((ivec2::move_ctor_counter == 2 || ivec2::move_ctor_counter == 3));
CHECK(ivec2::copy_ctor_counter == 0);
swap(val1, val2);
CHECK(val1 == "world"s);
CHECK(val2 == ivec2{1,2});
}
SUBCASE("ostream") {
std::stringstream str_stream;
CHECK_NOTHROW(str_stream << value{21} << " " << value{42});
CHECK_THROWS((str_stream << value{ivec2{1,2}}));
REQUIRE(str_stream.str() == "21 42");
}
SUBCASE("istream") {
std::stringstream str_stream{"21 42"};
value v{ivec2{1,2}};
CHECK_THROWS(str_stream >> v);
v = value{0};
CHECK_NOTHROW(str_stream >> v);
CHECK(v == 21);
CHECK_NOTHROW(str_stream >> v);
CHECK(v == 42);
}
SUBCASE("operator==") {
CHECK(value{ivec2{1,2}} == ivec2{1,2});
CHECK_FALSE(value{ivec2{1,2}} == ivec2{1,3});
CHECK(ivec2{1,2} == value{ivec2{1,2}});
CHECK_FALSE(ivec2{1,3} == value{ivec2{1,2}});
CHECK(value{ivec2{1,2}} == value{ivec2{1,2}});
CHECK_FALSE(value{ivec2{1,2}} == value{ivec2{1,3}});
{
class empty_class1 {};
class empty_class2 {};
CHECK_FALSE(operator==(value{empty_class1{}}, value{empty_class2{}}));
CHECK_THROWS(operator==(value{empty_class1{}}, value{empty_class1{}}));
}
}
}