Add cpp_function_template_specialization

This commit is contained in:
Jonathan Müller 2017-02-04 14:43:27 +01:00
commit 93f5ad5999
7 changed files with 126 additions and 5 deletions

View file

@ -47,6 +47,7 @@ namespace cppast
alias_template_t,
function_template_t,
function_template_specialization_t,
count,
};

View file

@ -37,6 +37,41 @@ namespace cppast
friend basic_builder<cpp_function_template, cpp_function_base>;
};
/// 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<cpp_function_template_specialization,
cpp_function_base, cpp_function_template>
{
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<const cpp_function_base&>(*begin());
}
private:
cpp_function_template_specialization(
std::unique_ptr<cpp_function_base> func,
type_safe::object_ref<const cpp_function_template> primary)
: cpp_template_specialization(std::unique_ptr<cpp_entity>(func.release()), primary)
{
}
cpp_entity_kind do_get_entity_kind() const noexcept override;
friend specialization_builder<cpp_function_template_specialization, cpp_function_base,
cpp_function_template>;
};
} // namespace cppast
#endif // CPPAST_CPP_FUNCTION_TEMPLATE_HPP_INCLUDED

View file

@ -5,6 +5,8 @@
#ifndef CPPAST_CPP_TEMPLATE_HPP_INCLUDED
#define CPPAST_CPP_TEMPLATE_HPP_INCLUDED
#include <vector>
#include <cppast/cpp_entity.hpp>
#include <cppast/cpp_entity_container.hpp>
#include <cppast/cpp_template_parameter.hpp>
@ -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<cpp_template_parameter> parameter_types() const noexcept
detail::iteratable_intrusive_list<cpp_template_parameter> 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 <typename T, typename EntityT>
template <class T, class EntityT>
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<EntityT> templ) : template_entity(new T(std::move(templ)))
{
}
@ -59,8 +61,7 @@ namespace cppast
std::unique_ptr<T> 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<cpp_entity> entity) : cpp_entity(entity->name())
{
add_child(std::move(entity));
@ -69,6 +70,69 @@ namespace cppast
private:
detail::intrusive_list<cpp_template_parameter> 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<cpp_template_argument>& 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 T, class EntityT, class TemplateT>
class specialization_builder : public basic_builder<T, EntityT>
{
public:
/// \effects Sets the entity that is being templated and the primary template.
specialization_builder(std::unique_ptr<EntityT> entity,
type_safe::object_ref<const TemplateT> templ)
{
this->template_entity = std::unique_ptr<T>(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<const cpp_template_specialization&>(*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<cpp_entity> entity,
type_safe::object_ref<const cpp_template> templ)
: cpp_template(std::move(entity)), templ_(templ)
{
}
private:
std::vector<cpp_template_argument> arguments_;
type_safe::object_ref<const cpp_template> templ_;
};
} // namespace cppast
#endif // CPPAST_CPP_TEMPLATE_HPP_INCLUDED

View file

@ -6,6 +6,7 @@
#define CPPAST_CPP_TEMPLATE_PARAMETER_HPP_INCLUDED
#include <type_safe/optional.hpp>
#include <type_safe/variant.hpp>
#include <cppast/cpp_entity.hpp>
#include <cppast/cpp_entity_container.hpp>
@ -237,6 +238,15 @@ namespace cppast
type_safe::optional<cpp_template_ref> 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_type>, std::unique_ptr<cpp_expression>,
cpp_template_ref>;
} // namespace cppast
#endif // CPPAST_CPP_TEMPLATE_PARAMETER_HPP_INCLUDED

View file

@ -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:

View file

@ -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;
}

View file

@ -66,6 +66,8 @@ bool detail::visit(const cpp_entity& e, detail::visitor_callback_t cb, void* fun
return handle_container<cpp_alias_template>(e, cb, functor);
case cpp_entity_kind::function_template_t:
return handle_container<cpp_function_template>(e, cb, functor);
case cpp_entity_kind::function_template_specialization_t:
return handle_container<cpp_function_template_specialization>(e, cb, functor);
case cpp_entity_kind::namespace_alias_t:
case cpp_entity_kind::using_directive_t: