mirror of
https://github.com/BlackMATov/meta.hpp.git
synced 2025-12-15 03:45:30 +07:00
start again from scratch
This commit is contained in:
@@ -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)
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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"
|
||||
@@ -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"
|
||||
@@ -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>},
|
||||
{}
|
||||
})} {}
|
||||
}
|
||||
@@ -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>(),
|
||||
{}, {}, {}, {}, {}, {}, {}, {}
|
||||
})} {}
|
||||
}
|
||||
@@ -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...>(),
|
||||
})} {}
|
||||
}
|
||||
@@ -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),
|
||||
{}
|
||||
})} {}
|
||||
}
|
||||
@@ -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>(),
|
||||
{}, {}
|
||||
})} {}
|
||||
}
|
||||
@@ -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),
|
||||
{}
|
||||
})} {}
|
||||
}
|
||||
@@ -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>(),
|
||||
})} {}
|
||||
}
|
||||
@@ -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),
|
||||
})} {}
|
||||
}
|
||||
@@ -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>(),
|
||||
})} {}
|
||||
}
|
||||
@@ -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),
|
||||
{}, {}, {}, {}, {}
|
||||
})} {}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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"
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
@@ -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();
|
||||
};
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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"
|
||||
@@ -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"
|
||||
@@ -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");
|
||||
}
|
||||
}
|
||||
@@ -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_);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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"
|
||||
@@ -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>());
|
||||
}
|
||||
@@ -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>());
|
||||
}
|
||||
}
|
||||
@@ -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});
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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") {
|
||||
}
|
||||
@@ -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") {
|
||||
}
|
||||
@@ -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") {
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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});
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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&&>);
|
||||
}
|
||||
}
|
||||
@@ -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") {
|
||||
}
|
||||
@@ -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"
|
||||
@@ -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");
|
||||
}
|
||||
}
|
||||
@@ -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"
|
||||
@@ -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());
|
||||
}
|
||||
}
|
||||
@@ -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());
|
||||
}
|
||||
}
|
||||
@@ -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>());
|
||||
}
|
||||
@@ -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());
|
||||
}
|
||||
}
|
||||
@@ -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));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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());
|
||||
}
|
||||
}
|
||||
@@ -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));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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>());
|
||||
}
|
||||
}
|
||||
@@ -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));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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());
|
||||
}
|
||||
}
|
||||
@@ -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());
|
||||
}
|
||||
}
|
||||
@@ -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());
|
||||
}
|
||||
}
|
||||
@@ -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
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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{}}));
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user