Skip to content

Commit

Permalink
Full list of translation unit reflected entities
Browse files Browse the repository at this point in the history
  • Loading branch information
Manu343726 committed Mar 24, 2019
1 parent 6a524b2 commit e76e34b
Show file tree
Hide file tree
Showing 10 changed files with 297 additions and 21 deletions.
2 changes: 2 additions & 0 deletions .clang-format
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ DerivePointerAlignment: 'false'
IncludeCategories:
- Regex: '.*\.tinyrefl'
Priority: 10000
- Regex: 'tinyrefl/entities.hpp'
Priority: 20000
IndentCaseLabels: 'false'
IndentWidth: '4'
IndentWrappedFunctionNames: 'true'
Expand Down
2 changes: 1 addition & 1 deletion examples/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
include(external/external.cmake)

add_library(tinyrefl-example-lib example.cpp)
tinyrefl_tool(TARGET tinyrefl-example-lib HEADERS example.hpp)
tinyrefl_tool(TARGET tinyrefl-example-lib HEADERS example.hpp example2.hpp)

add_tinyrefl_example(tinyrefl-example api.cpp)

Expand Down
40 changes: 40 additions & 0 deletions examples/api.cpp
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
#include "example.hpp"
#include "example2.hpp"
#include <iostream>
#include <sstream>
#include <tinyrefl/api.hpp>
#include "example.hpp.tinyrefl"
#include "example2.hpp.tinyrefl"
#include <tinyrefl/entities.hpp>


/*
Expand Down Expand Up @@ -203,4 +206,41 @@ int main()
.get_attribute(0) == "A",
"Expected [[A]] as first attribute");
#endif // TINYREFL_HAS_ENUM_VALUE_ATTRIBUTES

// Print all reflected entities
tinyrefl::visit_entities(
[](auto /* display_name */, auto index, auto entity, auto /* kind */) {
using Index = decltype(index);
using Entity = decltype(entity);

std::cout << "[entity " << Index::value << "] " << Entity::kind
<< " '" << tinyrefl::full_display_name<Entity>() << "'\n";
});

// Print all enums
tinyrefl::visit_enums([](auto /* display_name */, auto entity) {
using Entity = decltype(entity);

std::cout << "enum " << Entity::name.full_name() << "\n";

for(const auto value : entity)
{
std::cout << " - " << value.name() << "\n";
}
});

// Print all classes
tinyrefl::visit_classes([](auto /* display_name */, auto entity) {
using Entity = decltype(entity);

std::cout << "class " << Entity::name.full_name() << "\n";
});

// Print all member variables
tinyrefl::visit_entities<tinyrefl::entity::MEMBER_VARIABLE>(
[](auto /* display_name */, auto entity) {
using Entity = decltype(entity);

std::cout << "member variable " << Entity::name.full_name() << "\n";
});
}
64 changes: 64 additions & 0 deletions examples/example2.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
#ifndef TINYREFL_EXAMPLE2_HPP
#define TINYREFL_EXAMPLE2_HPP

#include <string>
#include <tinyrefl/utils/enum_value_attributes.hpp>

namespace example2
{

struct A
{
int a = 42;
};


struct B
{
const char* b = "hello";
};

enum class Enum
{
A,
B,
C,
D,
E = 42
};

struct C : public A, public B
{
public:
[[tinyrefl::ignore]] std::string ignore_me;
std::string hey_im_here = "hey, I'm here";
B subobject;

C() = default;
explicit C(const std::string& str) {}
[[C]] C(int a, int b) {}

[[f, f1, f2]] void f(int a, int b) const {};
[[f]] void f(int a, int b){};
[[f]] void f(){};
[[f]] void f() const {};

enum class Enum
{
A TINYREFL_ENUM_VALUE_ATTRIBUTE(A),
B TINYREFL_ENUM_VALUE_ATTRIBUTE(B),
C TINYREFL_ENUM_VALUE_ATTRIBUTE(C),
D TINYREFL_ENUM_VALUE_ATTRIBUTE(D),
E TINYREFL_ENUM_VALUE_ATTRIBUTE(E),
F TINYREFL_ENUM_VALUE_ATTRIBUTE(F)
};

[[e]] Enum e = Enum::A;
};

std::ostream& operator<<(std::ostream& os, const B& b);
std::ostream& operator<<(std::ostream& os, const Enum& value);
std::ostream& operator<<(std::ostream& os, const C::Enum& value);
} // namespace example2

#endif // TINYREFL_EXAMPLE2_HPP
4 changes: 2 additions & 2 deletions examples/rttr.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ auto register_rttr_type() -> std::enable_if_t<
std::is_enum<Enum>::value && tinyrefl::has_metadata<Enum>()>
{
register_rttr_enum<Enum>(rttr::registration::enumeration<Enum>(
tinyrefl::metadata<Enum>().name().full_name().begin()));
tinyrefl::metadata<Enum>::name.full_name().begin()));
}

template<typename Enum, typename Class>
Expand All @@ -66,7 +66,7 @@ auto register_rttr_member_enum(rttr::registration::class_<Class>& registration)
std::is_enum<Enum>::value && tinyrefl::has_metadata<Enum>()>
{
register_rttr_enum<Enum>(registration.template enumeration<Enum>(
tinyrefl::metadata<Enum>().name().full_name().begin()));
tinyrefl::metadata<Enum>::name.full_name().begin()));
}

template<typename Class>
Expand Down
6 changes: 6 additions & 0 deletions include/tinyrefl/api.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,12 @@ namespace tinyrefl

using entity = tinyrefl::backend::entity_kind;

template<entity Kind>
using kind_tag = TINYREFL_STATIC_VALUE(Kind);

template<entity Kind>
constexpr kind_tag<Kind> kind_tag_value{};

template<typename T>
using type_tag = ctti::type_tag<T>;

Expand Down
28 changes: 14 additions & 14 deletions include/tinyrefl/backend.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -814,7 +814,7 @@ struct enum_<Name, Enum, tinyrefl::meta::list<Values...>, Attributes>
: public metadata_with_attributes<Attributes>
{
static constexpr entity_kind kind = entity_kind::ENUM;
static constexpr ctti::name_t enum_name =
static constexpr ctti::name_t name =
tinyrefl::backend::string_constant<Name>();
using values = tinyrefl::meta::list<Values...>;
using enum_type = Enum;
Expand Down Expand Up @@ -932,9 +932,9 @@ struct enum_<Name, Enum, tinyrefl::meta::list<Values...>, Attributes>
return values::size;
}

constexpr const ctti::name_t& name() const
constexpr const ctti::name_t& name_() const
{
return enum_::enum_name;
return enum_::name;
}

constexpr const value_t& get_value(const ctti::detail::cstring& name) const
Expand Down Expand Up @@ -1021,19 +1021,13 @@ constexpr
enum_values;
template<typename Name, typename Enum, typename... Values, typename Attributes>
constexpr ctti::name_t
enum_<Name, Enum, tinyrefl::meta::list<Values...>, Attributes>::enum_name;
enum_<Name, Enum, tinyrefl::meta::list<Values...>, Attributes>::name;
template<typename Name, typename Enum, typename... Values, typename Attributes>
constexpr
typename enum_<Name, Enum, tinyrefl::meta::list<Values...>, Attributes>::
value_t enum_<Name, Enum, tinyrefl::meta::list<Values...>, Attributes>::
invalid_value;

template<typename Entity>
constexpr ctti::detail::cstring display_name(Entity = Entity{})
{
return Entity::name.name();
}

template<typename Entity>
struct has_custom_display_name
: tinyrefl::meta::bool_<
Expand All @@ -1042,30 +1036,34 @@ struct has_custom_display_name
};

template<typename Entity>
constexpr auto full_display_name(Entity = Entity{}) -> std::
constexpr auto full_display_name() -> std::
enable_if_t<!has_custom_display_name<Entity>::value, ctti::detail::cstring>
{
static_assert(std::is_class<Entity>::value, "");
return Entity::name.full_name();
}

template<typename Entity>
constexpr auto display_name(Entity = Entity{}) -> std::
constexpr auto display_name() -> std::
enable_if_t<!has_custom_display_name<Entity>::value, ctti::detail::cstring>
{
static_assert(std::is_class<Entity>::value, "");
return Entity::name.name();
}

template<typename Entity>
constexpr auto full_display_name(Entity = Entity{}) -> std::
constexpr auto full_display_name() -> std::
enable_if_t<has_custom_display_name<Entity>::value, ctti::detail::cstring>
{
static_assert(std::is_class<Entity>::value, "");
return Entity::full_display_name;
}

template<typename Entity>
constexpr auto display_name(Entity = Entity{}) -> std::
constexpr auto display_name() -> std::
enable_if_t<has_custom_display_name<Entity>::value, ctti::detail::cstring>
{
static_assert(std::is_class<Entity>::value, "");
return Entity::display_name;
}

Expand Down Expand Up @@ -1109,6 +1107,8 @@ constexpr auto display_name(Entity = Entity{}) -> std::

#define TINYREFL_SEQUENCE(elems) \
::tinyrefl::meta::list<TINYREFL_PP_UNWRAP elems>
#define TINYREFL_SEQUENCE_CAT(x, y) \
::tinyrefl::meta::cat_t<TINYREFL_PP_UNWRAP x, TINYREFL_PP_UNWRAP y>
#define TINYREFL_TYPE(name, fullname) TINYREFL_PP_UNWRAP fullname
#define TINYREFL_VALUE(type, value) \
::ctti::static_value<TINYREFL_PP_UNWRAP type, TINYREFL_PP_UNWRAP value>
Expand Down
73 changes: 73 additions & 0 deletions include/tinyrefl/entities.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
#ifndef TINYREFL_ENTITIES_HPP_INCLUDED
#define TINYREFL_ENTITIES_HPP_INCLUDED

#include <type_traits>

#if !defined(TINYREFL_API_HPP) || !defined(TINYREFL_ENTITIES)
#error \
"To use this header, first include your reflected headers, then <tinyrefl/api.hpp>, then your reflected headers generated code (.tinyrefl header files), and then this header"
#endif

namespace tinyrefl
{

using entities = tinyrefl::meta::fmap_t<
tinyrefl::meta::defer<tinyrefl::backend::metadata_of_entity_name>,
TINYREFL_ENTITIES>;

template<typename Entity>
constexpr ctti::detail::cstring display_name(Entity entity = Entity{})
{
static_assert(std::is_class<Entity>::value, "");
return tinyrefl::backend::display_name<Entity>();
}

template<typename Entity>
constexpr ctti::detail::cstring full_display_name(Entity entity = Entity{})
{
static_assert(std::is_class<Entity>::value, "");
return tinyrefl::backend::full_display_name<Entity>();
}

template<typename... Visitors>
void visit_entities(Visitors... visitors)
{
tinyrefl::meta::foreach<tinyrefl::entities>(
[visitor = tinyrefl::overloaded_function_default(visitors...)](
auto type, auto index) {
using Entity = typename decltype(type)::type;

static_assert(std::is_class<Entity>::value, "");

visitor(
tinyrefl::display_name<Entity>(),
index,
Entity{},
kind_tag_value<Entity::kind>);
});
}

template<tinyrefl::entity Kind, typename Visitor>
void visit_entities(Visitor visitor)
{
visit_entities(
[visitor](
auto display_name, auto /* index */, auto entity, kind_tag<Kind>) {
visitor(display_name, entity);
});
}

template<typename Visitor>
void visit_classes(Visitor visitor)
{
visit_entities<tinyrefl::entity::CLASS>(visitor);
}

template<typename Visitor>
void visit_enums(Visitor visitor)
{
visit_entities<tinyrefl::entity::ENUM>(visitor);
}
} // namespace tinyrefl

#endif // TINYREFL_ENTITIES_HPP_INCLUDED
16 changes: 16 additions & 0 deletions tests/static/api.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,13 @@
#include <tinyrefl/utils/enum_value_attributes.hpp>
#include "../example.hpp.tinyrefl"
#include "members.hpp.tinyrefl"
#include <tinyrefl/entities.hpp>
#include CTTI_STATIC_TESTS_HEADER

#if TINYREFL_GENERATED_FILE_COUNT != 2
#error "Expected two tinyrefl codegen headers"
#endif

using check = tinyrefl::test::AssertMetadataAvailableForTemplateParam<foo::Foo>;
EXPECT_TRUE(std::is_pointer<check*>::value);
EXPECT_FALSE(tinyrefl::has_attribute<foo::Foo>("attribute"));
Expand Down Expand Up @@ -298,3 +303,14 @@ EXPECT_EQ(
tinyrefl::entity_metadata<
"my_namespace::MyClass::overloaded(int)"_id>::arg_names[0],
"firstArg");

EXPECT_TRUE(tinyrefl::has_entity_metadata<"my_namespace::MyClass::Enum"_id>());
EXPECT_TRUE(std::is_same<
tinyrefl::entity_metadata<"my_namespace::MyClass::Enum"_id>,
tinyrefl::metadata<my_namespace::MyClass::Enum>>::value);

EXPECT_TRUE(
std::is_same<
tinyrefl::meta::
filter_t<tinyrefl::meta::defer<std::is_class>, tinyrefl::entities>,
tinyrefl::entities>::value);
Loading

0 comments on commit e76e34b

Please sign in to comment.