From 93f5ad5999ef48528478d3e97d4e85a76e3af61e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonathan=20M=C3=BCller?= Date: Sat, 4 Feb 2017 14:43:27 +0100 Subject: [PATCH] Add cpp_function_template_specialization --- include/cppast/cpp_entity_kind.hpp | 1 + include/cppast/cpp_function_template.hpp | 35 +++++++++++ include/cppast/cpp_template.hpp | 74 +++++++++++++++++++++-- include/cppast/cpp_template_parameter.hpp | 10 +++ src/cpp_entity_kind.cpp | 4 ++ src/cpp_function_template.cpp | 5 ++ src/visitor.cpp | 2 + 7 files changed, 126 insertions(+), 5 deletions(-) diff --git a/include/cppast/cpp_entity_kind.hpp b/include/cppast/cpp_entity_kind.hpp index b36dcba..847d1ec 100644 --- a/include/cppast/cpp_entity_kind.hpp +++ b/include/cppast/cpp_entity_kind.hpp @@ -47,6 +47,7 @@ namespace cppast alias_template_t, function_template_t, + function_template_specialization_t, count, }; diff --git a/include/cppast/cpp_function_template.hpp b/include/cppast/cpp_function_template.hpp index de0f846..0f81ea9 100644 --- a/include/cppast/cpp_function_template.hpp +++ b/include/cppast/cpp_function_template.hpp @@ -37,6 +37,41 @@ namespace cppast friend basic_builder; }; + + /// A [cppast::cpp_entity]() modelling a function template specialization. + class cpp_function_template_specialization final : public cpp_template_specialization + { + public: + /// Builder for [cppast::cpp_function_template_specialization](). + class builder : public specialization_builder + { + public: + using specialization_builder::specialization_builder; + + private: + using specialization_builder::add_parameter; + }; + + /// A reference to the function that is being specialized. + const cpp_function_base& function() const noexcept + { + return static_cast(*begin()); + } + + private: + cpp_function_template_specialization( + std::unique_ptr func, + type_safe::object_ref primary) + : cpp_template_specialization(std::unique_ptr(func.release()), primary) + { + } + + cpp_entity_kind do_get_entity_kind() const noexcept override; + + friend specialization_builder; + }; } // namespace cppast #endif // CPPAST_CPP_FUNCTION_TEMPLATE_HPP_INCLUDED diff --git a/include/cppast/cpp_template.hpp b/include/cppast/cpp_template.hpp index a7534ff..d404b13 100644 --- a/include/cppast/cpp_template.hpp +++ b/include/cppast/cpp_template.hpp @@ -5,6 +5,8 @@ #ifndef CPPAST_CPP_TEMPLATE_HPP_INCLUDED #define CPPAST_CPP_TEMPLATE_HPP_INCLUDED +#include + #include #include #include @@ -19,7 +21,7 @@ namespace cppast public: /// \returns An iteratable object iterating over the [cppast::cpp_template_parameter]() entities. /// \notes These may be empty for a full specialization. - detail::iteratable_intrusive_list parameter_types() const noexcept + detail::iteratable_intrusive_list parameters() const noexcept { return type_safe::ref(parameters_); } @@ -28,11 +30,11 @@ namespace cppast /// Builder class for templates. /// /// Inherit from it to provide additional setter. - template + template class basic_builder { public: - /// \effects Sets the name and the entity that is begin templated. + /// \effects Sets the entity that is begin templated. basic_builder(std::unique_ptr templ) : template_entity(new T(std::move(templ))) { } @@ -59,8 +61,7 @@ namespace cppast std::unique_ptr template_entity; }; - /// \effects Sets the name of the template and the entity to be templated. - /// \notes It does not include the parameters. + /// \effects Sets the entity to be templated. cpp_template(std::unique_ptr entity) : cpp_entity(entity->name()) { add_child(std::move(entity)); @@ -69,6 +70,69 @@ namespace cppast private: detail::intrusive_list parameters_; }; + + /// Base class for all entities modelling a C++ template specialization. + class cpp_template_specialization : public cpp_template + { + public: + /// \returns A reference to the template that is being specialized. + const cpp_template& primary_template() const noexcept + { + return *templ_; + } + + /// \returns An iteratable object iterating over the [cppast::cpp_template_argument]()s. + /// \exclude return + const std::vector& arguments() const noexcept + { + return arguments_; + } + + /// \returns Whether or not the specialization is a full specialization. + bool is_full_specialization() const noexcept + { + // if no template parameters are given, it is a full specialization + return parameters().empty(); + } + + protected: + /// Builder class for specializations. + /// + /// Inherit from it to provide additional setter. + template + class specialization_builder : public basic_builder + { + public: + /// \effects Sets the entity that is being templated and the primary template. + specialization_builder(std::unique_ptr entity, + type_safe::object_ref templ) + { + this->template_entity = std::unique_ptr(new T(std::move(entity), templ)); + } + + /// \effects Adds the next argument for the [cppast::cpp_template_parameter]() of the primary template. + void add_argument(cpp_template_argument arg) + { + auto specialization = + static_cast(*this->template_entity); + specialization.arguments_.push_back(std::move(arg)); + } + + protected: + specialization_builder() = default; + }; + + /// \effects Sets the entity that is being templated and the primary template. + cpp_template_specialization(std::unique_ptr entity, + type_safe::object_ref templ) + : cpp_template(std::move(entity)), templ_(templ) + { + } + + private: + std::vector arguments_; + type_safe::object_ref templ_; + }; } // namespace cppast #endif // CPPAST_CPP_TEMPLATE_HPP_INCLUDED diff --git a/include/cppast/cpp_template_parameter.hpp b/include/cppast/cpp_template_parameter.hpp index ac8219e..a2fd485 100644 --- a/include/cppast/cpp_template_parameter.hpp +++ b/include/cppast/cpp_template_parameter.hpp @@ -6,6 +6,7 @@ #define CPPAST_CPP_TEMPLATE_PARAMETER_HPP_INCLUDED #include +#include #include #include @@ -237,6 +238,15 @@ namespace cppast type_safe::optional default_; cpp_template_keyword keyword_; }; + + /// An argument for a [cppast::cpp_template_parameter](). + /// + /// It is a [ts::variant]() of [cppast::cpp_type]() (for [cppast::cpp_template_type_parameter]()), + /// [cppast::cpp_expression]() (for [cppast::cpp_non_type_template_parameter]()) and [cppast::cpp_template_ref]() + /// (for [cppast::cpp_template_template_parameter](). + using cpp_template_argument = + type_safe::variant, std::unique_ptr, + cpp_template_ref>; } // namespace cppast #endif // CPPAST_CPP_TEMPLATE_PARAMETER_HPP_INCLUDED diff --git a/src/cpp_entity_kind.cpp b/src/cpp_entity_kind.cpp index 76d19df..40c4ed8 100644 --- a/src/cpp_entity_kind.cpp +++ b/src/cpp_entity_kind.cpp @@ -71,6 +71,8 @@ const char* cppast::to_string(cpp_entity_kind kind) noexcept return "alias template"; case cpp_entity_kind::function_template_t: return "function template"; + case cpp_entity_kind::function_template_specialization_t: + return "function template specialization"; case cpp_entity_kind::count: break; @@ -111,6 +113,7 @@ bool cppast::is_type(cpp_entity_kind kind) noexcept case cpp_entity_kind::template_template_parameter_t: case cpp_entity_kind::alias_template_t: case cpp_entity_kind::function_template_t: + case cpp_entity_kind::function_template_specialization_t: case cpp_entity_kind::count: break; } @@ -124,6 +127,7 @@ bool cppast::is_template(cpp_entity_kind kind) noexcept { case cpp_entity_kind::alias_template_t: case cpp_entity_kind::function_template_t: + case cpp_entity_kind::function_template_specialization_t: return true; case cpp_entity_kind::file_t: diff --git a/src/cpp_function_template.cpp b/src/cpp_function_template.cpp index 0ad122b..64f262e 100644 --- a/src/cpp_function_template.cpp +++ b/src/cpp_function_template.cpp @@ -12,3 +12,8 @@ cpp_entity_kind cpp_function_template::do_get_entity_kind() const noexcept { return cpp_entity_kind::function_template_t; } + +cpp_entity_kind cpp_function_template_specialization::do_get_entity_kind() const noexcept +{ + return cpp_entity_kind::function_template_specialization_t; +} diff --git a/src/visitor.cpp b/src/visitor.cpp index 828ca89..10c9347 100644 --- a/src/visitor.cpp +++ b/src/visitor.cpp @@ -66,6 +66,8 @@ bool detail::visit(const cpp_entity& e, detail::visitor_callback_t cb, void* fun return handle_container(e, cb, functor); case cpp_entity_kind::function_template_t: return handle_container(e, cb, functor); + case cpp_entity_kind::function_template_specialization_t: + return handle_container(e, cb, functor); case cpp_entity_kind::namespace_alias_t: case cpp_entity_kind::using_directive_t: