Fixed handling of array template specialization types
This commit is contained in:
@@ -23,7 +23,7 @@ Full documentation can be found [here](./docs/README.md).
|
|||||||
Main features supported so far include:
|
Main features supported so far include:
|
||||||
|
|
||||||
* **Class diagram generation**
|
* **Class diagram generation**
|
||||||
* Basic class properties and methods including visibility
|
* Basic class properties and methods including access
|
||||||
* Class relationships including associations, aggregations, dependencies and friendship
|
* Class relationships including associations, aggregations, dependencies and friendship
|
||||||
* Template instantiation relationships
|
* Template instantiation relationships
|
||||||
* Relationship inference from C++ containers and smart pointers
|
* Relationship inference from C++ containers and smart pointers
|
||||||
|
|||||||
@@ -583,41 +583,39 @@ template_parameter template_builder::process_type_argument(
|
|||||||
|
|
||||||
argument = try_as_function_prototype(parent, cls, template_decl, type,
|
argument = try_as_function_prototype(parent, cls, template_decl, type,
|
||||||
template_instantiation, argument_index);
|
template_instantiation, argument_index);
|
||||||
|
|
||||||
if (argument)
|
if (argument)
|
||||||
return *argument;
|
return *argument;
|
||||||
|
|
||||||
argument = try_as_member_pointer(parent, cls, template_decl, type,
|
argument = try_as_member_pointer(parent, cls, template_decl, type,
|
||||||
template_instantiation, argument_index);
|
template_instantiation, argument_index);
|
||||||
|
if (argument)
|
||||||
|
return *argument;
|
||||||
|
|
||||||
|
argument = try_as_array(parent, cls, template_decl, type,
|
||||||
|
template_instantiation, argument_index);
|
||||||
if (argument)
|
if (argument)
|
||||||
return *argument;
|
return *argument;
|
||||||
|
|
||||||
argument = try_as_template_specialization_type(parent, cls, template_decl,
|
argument = try_as_template_specialization_type(parent, cls, template_decl,
|
||||||
type, template_instantiation, argument_index);
|
type, template_instantiation, argument_index);
|
||||||
|
|
||||||
if (argument)
|
if (argument)
|
||||||
return *argument;
|
return *argument;
|
||||||
|
|
||||||
argument = try_as_template_parm_type(cls, template_decl, type);
|
argument = try_as_template_parm_type(cls, template_decl, type);
|
||||||
|
|
||||||
if (argument)
|
if (argument)
|
||||||
return *argument;
|
return *argument;
|
||||||
|
|
||||||
argument = try_as_lambda(cls, template_decl, type);
|
argument = try_as_lambda(cls, template_decl, type);
|
||||||
|
|
||||||
if (argument)
|
if (argument)
|
||||||
return *argument;
|
return *argument;
|
||||||
|
|
||||||
argument = try_as_record_type(parent, cls, template_decl, type,
|
argument = try_as_record_type(parent, cls, template_decl, type,
|
||||||
template_instantiation, argument_index);
|
template_instantiation, argument_index);
|
||||||
|
|
||||||
if (argument)
|
if (argument)
|
||||||
return *argument;
|
return *argument;
|
||||||
|
|
||||||
argument = try_as_enum_type(
|
argument = try_as_enum_type(
|
||||||
parent, cls, template_decl, type, template_instantiation);
|
parent, cls, template_decl, type, template_instantiation);
|
||||||
|
|
||||||
if (argument)
|
if (argument)
|
||||||
return *argument;
|
return *argument;
|
||||||
|
|
||||||
@@ -894,6 +892,7 @@ std::optional<template_parameter> template_builder::try_as_array(
|
|||||||
->getSize()
|
->getSize()
|
||||||
.getLimitedValue())));
|
.getLimitedValue())));
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Handle variable sized arrays
|
// TODO: Handle variable sized arrays
|
||||||
|
|
||||||
return argument;
|
return argument;
|
||||||
@@ -922,9 +921,17 @@ std::optional<template_parameter> template_builder::try_as_function_prototype(
|
|||||||
argument.add_template_param(return_arg);
|
argument.add_template_param(return_arg);
|
||||||
|
|
||||||
// Set function template argument types
|
// Set function template argument types
|
||||||
|
if (function_type->isVariadic() && function_type->param_types().empty()) {
|
||||||
|
auto fallback_arg = template_parameter::make_argument({});
|
||||||
|
fallback_arg.is_ellipsis(true);
|
||||||
|
argument.add_template_param(std::move(fallback_arg));
|
||||||
|
}
|
||||||
|
else {
|
||||||
for (const auto ¶m_type : function_type->param_types()) {
|
for (const auto ¶m_type : function_type->param_types()) {
|
||||||
argument.add_template_param(process_type_argument(parent, cls,
|
argument.add_template_param(
|
||||||
template_decl, param_type, template_instantiation, argument_index));
|
process_type_argument(parent, cls, template_decl, param_type,
|
||||||
|
template_instantiation, argument_index));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return argument;
|
return argument;
|
||||||
|
|||||||
@@ -138,6 +138,21 @@ template_parameter template_parameter::make_unexposed_argument(
|
|||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool template_parameter::is_specialization() const
|
||||||
|
{
|
||||||
|
return is_function_template() || is_array() || is_data_pointer() ||
|
||||||
|
is_member_pointer() || !deduced_context().empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool template_parameter::is_same_specialization(
|
||||||
|
const template_parameter &other) const
|
||||||
|
{
|
||||||
|
return is_array() == other.is_array() &&
|
||||||
|
is_function_template() == other.is_function_template() &&
|
||||||
|
is_data_pointer() == other.is_data_pointer() &&
|
||||||
|
is_member_pointer() == other.is_member_pointer();
|
||||||
|
}
|
||||||
|
|
||||||
void template_parameter::set_type(const std::string &type)
|
void template_parameter::set_type(const std::string &type)
|
||||||
{
|
{
|
||||||
assert(kind_ != template_parameter_kind_t::template_type);
|
assert(kind_ != template_parameter_kind_t::template_type);
|
||||||
@@ -212,11 +227,18 @@ int template_parameter::calculate_specialization_match(
|
|||||||
|
|
||||||
// If the potential base template has a deduction context (e.g. const&),
|
// If the potential base template has a deduction context (e.g. const&),
|
||||||
// the specialization must have the same and possibly more
|
// the specialization must have the same and possibly more
|
||||||
if (!base_template_parameter.deduced_context().empty() &&
|
if (base_template_parameter.is_specialization()) {
|
||||||
!util::starts_with(
|
if (!deduced_context().empty() &&
|
||||||
deduced_context(), base_template_parameter.deduced_context()))
|
(base_template_parameter.deduced_context().empty() ||
|
||||||
|
!util::starts_with(deduced_context(),
|
||||||
|
base_template_parameter.deduced_context())))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
if (!base_template_parameter.deduced_context().empty() &&
|
||||||
|
deduced_context().empty())
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
if (is_template_parameter() &&
|
if (is_template_parameter() &&
|
||||||
base_template_parameter.is_template_parameter() &&
|
base_template_parameter.is_template_parameter() &&
|
||||||
template_params().empty() &&
|
template_params().empty() &&
|
||||||
@@ -245,9 +267,6 @@ int template_parameter::calculate_specialization_match(
|
|||||||
if (base_template_parameter.is_array() && !is_array())
|
if (base_template_parameter.is_array() && !is_array())
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (base_template_parameter.is_array() && is_array())
|
|
||||||
res++;
|
|
||||||
|
|
||||||
if (base_template_parameter.is_function_template() &&
|
if (base_template_parameter.is_function_template() &&
|
||||||
!is_function_template())
|
!is_function_template())
|
||||||
return 0;
|
return 0;
|
||||||
@@ -259,7 +278,8 @@ int template_parameter::calculate_specialization_match(
|
|||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (!base_template_parameter.template_params().empty() &&
|
if (!base_template_parameter.template_params().empty() &&
|
||||||
!template_params().empty()) {
|
!template_params().empty() &&
|
||||||
|
is_same_specialization(base_template_parameter)) {
|
||||||
auto params_match = calculate_template_params_specialization_match(
|
auto params_match = calculate_template_params_specialization_match(
|
||||||
template_params(), base_template_parameter.template_params());
|
template_params(), base_template_parameter.template_params());
|
||||||
|
|
||||||
@@ -270,8 +290,21 @@ int template_parameter::calculate_specialization_match(
|
|||||||
}
|
}
|
||||||
else if ((base_template_parameter.is_template_parameter() ||
|
else if ((base_template_parameter.is_template_parameter() ||
|
||||||
base_template_parameter.is_template_template_parameter()) &&
|
base_template_parameter.is_template_template_parameter()) &&
|
||||||
!is_template_parameter())
|
!is_template_parameter()) {
|
||||||
return 1;
|
return 1;
|
||||||
|
}
|
||||||
|
else if (base_template_parameter.is_template_parameter() &&
|
||||||
|
base_template_parameter.template_params().empty()) {
|
||||||
|
// If the base is a regular template param, only possible with deduced
|
||||||
|
// context (deduced context already matches if exists)
|
||||||
|
res++;
|
||||||
|
|
||||||
|
if (!deduced_context().empty() &&
|
||||||
|
!base_template_parameter.deduced_context().empty() &&
|
||||||
|
util::starts_with(
|
||||||
|
deduced_context(), base_template_parameter.deduced_context()))
|
||||||
|
res += base_template_parameter.deduced_context().size();
|
||||||
|
}
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
@@ -335,13 +368,26 @@ std::string template_parameter::to_string(
|
|||||||
const clanguml::common::model::namespace_ &using_namespace, bool relative,
|
const clanguml::common::model::namespace_ &using_namespace, bool relative,
|
||||||
bool skip_qualifiers) const
|
bool skip_qualifiers) const
|
||||||
{
|
{
|
||||||
if (is_elipssis())
|
if (is_ellipsis())
|
||||||
return "...";
|
return "...";
|
||||||
|
|
||||||
using clanguml::common::model::namespace_;
|
using clanguml::common::model::namespace_;
|
||||||
|
|
||||||
assert(!(type().has_value() && concept_constraint().has_value()));
|
assert(!(type().has_value() && concept_constraint().has_value()));
|
||||||
|
|
||||||
|
if (is_array()) {
|
||||||
|
auto it = template_params_.begin();
|
||||||
|
auto element_type = it->to_string(using_namespace, relative);
|
||||||
|
std::advance(it, 1);
|
||||||
|
|
||||||
|
std::vector<std::string> dimension_args;
|
||||||
|
for (; it != template_params_.end(); it++)
|
||||||
|
dimension_args.push_back(it->to_string(using_namespace, relative));
|
||||||
|
|
||||||
|
return fmt::format(
|
||||||
|
"{}[{}]", element_type, fmt::join(dimension_args, "]["));
|
||||||
|
}
|
||||||
|
|
||||||
if (is_function_template()) {
|
if (is_function_template()) {
|
||||||
auto it = template_params_.begin();
|
auto it = template_params_.begin();
|
||||||
auto return_type = it->to_string(using_namespace, relative);
|
auto return_type = it->to_string(using_namespace, relative);
|
||||||
@@ -589,13 +635,19 @@ const std::deque<context> &template_parameter::deduced_context() const
|
|||||||
{
|
{
|
||||||
return context_;
|
return context_;
|
||||||
}
|
}
|
||||||
|
|
||||||
void template_parameter::deduced_context(const std::deque<context> &c)
|
void template_parameter::deduced_context(const std::deque<context> &c)
|
||||||
{
|
{
|
||||||
context_ = c;
|
context_ = c;
|
||||||
}
|
}
|
||||||
|
|
||||||
void template_parameter::is_elipssis(bool e) { is_elipssis_ = e; }
|
void template_parameter::is_ellipsis(bool e) { is_ellipsis_ = e; }
|
||||||
bool template_parameter::is_elipssis() const { return is_elipssis_; }
|
|
||||||
|
bool template_parameter::is_ellipsis() const { return is_ellipsis_; }
|
||||||
|
|
||||||
|
void template_parameter::is_noexcept(bool e) { is_noexcept_ = e; }
|
||||||
|
|
||||||
|
bool template_parameter::is_noexcept() const { return is_noexcept_; }
|
||||||
|
|
||||||
int calculate_template_params_specialization_match(
|
int calculate_template_params_specialization_match(
|
||||||
const std::vector<template_parameter> &specialization_params,
|
const std::vector<template_parameter> &specialization_params,
|
||||||
@@ -620,6 +672,7 @@ int calculate_template_params_specialization_match(
|
|||||||
template_params.at(template_index));
|
template_params.at(template_index));
|
||||||
|
|
||||||
if (match == 0) {
|
if (match == 0) {
|
||||||
|
// If any of the matches is 0 - the entire match fails
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -131,6 +131,10 @@ public:
|
|||||||
|
|
||||||
bool is_association() const;
|
bool is_association() const;
|
||||||
|
|
||||||
|
bool is_specialization() const;
|
||||||
|
|
||||||
|
bool is_same_specialization(const template_parameter &other) const;
|
||||||
|
|
||||||
bool find_nested_relationships(
|
bool find_nested_relationships(
|
||||||
std::vector<std::pair<int64_t, common::model::relationship_t>>
|
std::vector<std::pair<int64_t, common::model::relationship_t>>
|
||||||
&nested_relationships,
|
&nested_relationships,
|
||||||
@@ -147,7 +151,6 @@ public:
|
|||||||
void set_kind(template_parameter_kind_t kind);
|
void set_kind(template_parameter_kind_t kind);
|
||||||
|
|
||||||
bool is_unexposed() const;
|
bool is_unexposed() const;
|
||||||
|
|
||||||
void set_unexposed(bool unexposed);
|
void set_unexposed(bool unexposed);
|
||||||
|
|
||||||
void is_function_template(bool ft);
|
void is_function_template(bool ft);
|
||||||
@@ -166,8 +169,11 @@ public:
|
|||||||
const std::deque<context> &deduced_context() const;
|
const std::deque<context> &deduced_context() const;
|
||||||
void deduced_context(const std::deque<context> &c);
|
void deduced_context(const std::deque<context> &c);
|
||||||
|
|
||||||
void is_elipssis(bool e);
|
void is_ellipsis(bool e);
|
||||||
bool is_elipssis() const;
|
bool is_ellipsis() const;
|
||||||
|
|
||||||
|
void is_noexcept(bool e);
|
||||||
|
bool is_noexcept() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
template_parameter() = default;
|
template_parameter() = default;
|
||||||
@@ -194,7 +200,9 @@ private:
|
|||||||
/// Can only be true when is_template_parameter_ is true
|
/// Can only be true when is_template_parameter_ is true
|
||||||
bool is_template_template_parameter_{false};
|
bool is_template_template_parameter_{false};
|
||||||
|
|
||||||
bool is_elipssis_{false};
|
bool is_ellipsis_{false};
|
||||||
|
|
||||||
|
bool is_noexcept_{false};
|
||||||
|
|
||||||
/// Whether the template parameter is variadic
|
/// Whether the template parameter is variadic
|
||||||
bool is_variadic_{false};
|
bool is_variadic_{false};
|
||||||
|
|||||||
@@ -17,6 +17,10 @@ template <typename U> struct A<std::map<std::string, U> &> {
|
|||||||
template <>
|
template <>
|
||||||
struct A<std::map<std::string, std::map<std::string, std::string>> &> { };
|
struct A<std::map<std::string, std::map<std::string, std::string>> &> { };
|
||||||
|
|
||||||
|
template <typename U> struct A<U **> {
|
||||||
|
U **u;
|
||||||
|
};
|
||||||
|
|
||||||
template <typename U> struct A<U **const *> {
|
template <typename U> struct A<U **const *> {
|
||||||
U ***u;
|
U ***u;
|
||||||
};
|
};
|
||||||
@@ -75,6 +79,13 @@ template <int N> struct A<char[N]> {
|
|||||||
template <> struct A<char[1000]> {
|
template <> struct A<char[1000]> {
|
||||||
std::vector<char> n;
|
std::vector<char> n;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template <int K, int L, int M> struct A<char[K][L][M]> { char klm[K][L][M]; };
|
||||||
|
|
||||||
|
template <typename U> struct A<U(...)> {
|
||||||
|
bool u;
|
||||||
|
};
|
||||||
|
|
||||||
//
|
//
|
||||||
// template <typename T> struct eval;
|
// template <typename T> struct eval;
|
||||||
//
|
//
|
||||||
|
|||||||
@@ -51,36 +51,22 @@ TEST_CASE("t00062", "[test-case][class]")
|
|||||||
REQUIRE_THAT(puml, IsClassTemplate("A", "char[N]"));
|
REQUIRE_THAT(puml, IsClassTemplate("A", "char[N]"));
|
||||||
REQUIRE_THAT(puml, IsClassTemplate("A", "char[1000]"));
|
REQUIRE_THAT(puml, IsClassTemplate("A", "char[1000]"));
|
||||||
|
|
||||||
// Check if class templates exist
|
REQUIRE_THAT(puml, IsClassTemplate("A", "U(...)"));
|
||||||
// REQUIRE_THAT(puml, IsClassTemplate("A", "T,P,CMP,int N"));
|
|
||||||
|
|
||||||
// Check concepts
|
REQUIRE_THAT(puml, IsInstantiation(_A("A<T>"), _A("A<U &>")));
|
||||||
// REQUIRE_THAT(puml, IsConcept(_A("AConcept<T>")));
|
REQUIRE_THAT(puml, IsInstantiation(_A("A<T>"), _A("A<U &&>")));
|
||||||
// REQUIRE_THAT(puml,
|
REQUIRE_THAT(puml, IsInstantiation(_A("A<T>"), _A("A<M C::*>")));
|
||||||
// IsConceptRequirement(
|
REQUIRE_THAT(puml, IsInstantiation(_A("A<U &&>"), _A("A<M C::* &&>")));
|
||||||
// _A("AConcept<T,P>"), "sizeof (T) > sizeof (P)"));
|
|
||||||
|
|
||||||
// Check if all enums exist
|
REQUIRE_THAT(puml, IsInstantiation(_A("A<T>"), _A("A<M (C::*)(Arg)>")));
|
||||||
// REQUIRE_THAT(puml, IsEnum(_A("Lights")));
|
REQUIRE_THAT(puml,
|
||||||
|
IsInstantiation(_A("A<M (C::*)(Arg)>"), _A("A<int (C::*)(bool)>")));
|
||||||
|
|
||||||
// Check if all inner classes exist
|
REQUIRE_THAT(puml, IsInstantiation(_A("A<T>"), _A("A<char[N]>")));
|
||||||
// REQUIRE_THAT(puml, IsInnerClass(_A("A"), _A("AA")));
|
REQUIRE_THAT(
|
||||||
|
puml, IsInstantiation(_A("A<char[N]>"), _A("A<char[1000]>")));
|
||||||
|
|
||||||
// Check if all inheritance relationships exist
|
REQUIRE_THAT(puml, IsInstantiation(_A("A<T>"), _A("A<U(...)>")));
|
||||||
// REQUIRE_THAT(puml, IsBaseClass(_A("Base"), _A("Child")));
|
|
||||||
|
|
||||||
// Check if all methods exist
|
|
||||||
// REQUIRE_THAT(puml, (IsMethod<Public, Const>("foo")));
|
|
||||||
|
|
||||||
// Check if all fields exist
|
|
||||||
// REQUIRE_THAT(puml, (IsField<Private>("private_member", "int")));
|
|
||||||
|
|
||||||
// Check if all relationships exist
|
|
||||||
// REQUIRE_THAT(puml, IsAssociation(_A("D"), _A("A"), "-as"));
|
|
||||||
// REQUIRE_THAT(puml, IsDependency(_A("R"), _A("B")));
|
|
||||||
// REQUIRE_THAT(puml, IsAggregation(_A("R"), _A("D"), "-ag"));
|
|
||||||
// REQUIRE_THAT(puml, IsComposition(_A("R"), _A("D"), "-ac"));
|
|
||||||
// REQUIRE_THAT(puml, IsInstantiation(_A("ABCD::F<T>"), _A("F<int>")));
|
|
||||||
|
|
||||||
save_puml(
|
save_puml(
|
||||||
config.output_directory() + "/" + diagram->name + ".puml", puml);
|
config.output_directory() + "/" + diagram->name + ".puml", puml);
|
||||||
|
|||||||
@@ -236,6 +236,8 @@ struct AliasMatcher {
|
|||||||
util::replace_all(name, ")", "\\)");
|
util::replace_all(name, ")", "\\)");
|
||||||
util::replace_all(name, " ", "\\s");
|
util::replace_all(name, " ", "\\s");
|
||||||
util::replace_all(name, "*", "\\*");
|
util::replace_all(name, "*", "\\*");
|
||||||
|
util::replace_all(name, "[", "\\[");
|
||||||
|
util::replace_all(name, "]", "\\]");
|
||||||
|
|
||||||
patterns.push_back(
|
patterns.push_back(
|
||||||
std::regex{"class\\s\"" + name + "\"\\sas\\s" + alias_regex});
|
std::regex{"class\\s\"" + name + "\"\\sas\\s" + alias_regex});
|
||||||
|
|||||||
@@ -318,4 +318,92 @@ TEST_CASE(
|
|||||||
|
|
||||||
CHECK(tp2.calculate_specialization_match(tp1));
|
CHECK(tp2.calculate_specialization_match(tp1));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
using clanguml::common::model::context;
|
||||||
|
using clanguml::common::model::rpqualifier;
|
||||||
|
|
||||||
|
auto tp1 = template_parameter::make_template_type({});
|
||||||
|
tp1.is_data_pointer(true);
|
||||||
|
tp1.add_template_param(template_parameter::make_template_type("T"));
|
||||||
|
tp1.add_template_param(template_parameter::make_template_type("C"));
|
||||||
|
|
||||||
|
CHECK(tp1.is_specialization());
|
||||||
|
|
||||||
|
auto tp2 = template_parameter::make_template_type({});
|
||||||
|
tp2.is_data_pointer(true);
|
||||||
|
tp2.add_template_param(template_parameter::make_argument("T"));
|
||||||
|
tp2.add_template_param(template_parameter::make_template_type("C"));
|
||||||
|
tp2.push_context(context{.pr = rpqualifier::kRValueReference});
|
||||||
|
|
||||||
|
CHECK(tp2.is_specialization());
|
||||||
|
|
||||||
|
CHECK(tp2.calculate_specialization_match(tp1) == 0);
|
||||||
|
CHECK(tp1.calculate_specialization_match(tp2) == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
using clanguml::common::model::context;
|
||||||
|
using clanguml::common::model::rpqualifier;
|
||||||
|
|
||||||
|
auto tp1 = template_parameter::make_template_type("T");
|
||||||
|
tp1.push_context(context{.pr = rpqualifier::kRValueReference});
|
||||||
|
CHECK(tp1.is_specialization());
|
||||||
|
|
||||||
|
auto tp2 = template_parameter::make_template_type({});
|
||||||
|
tp2.is_data_pointer(true);
|
||||||
|
tp2.add_template_param(template_parameter::make_template_type("T"));
|
||||||
|
tp2.add_template_param(template_parameter::make_template_type("C"));
|
||||||
|
tp2.push_context(context{.pr = rpqualifier::kRValueReference});
|
||||||
|
|
||||||
|
CHECK(tp2.is_specialization());
|
||||||
|
|
||||||
|
CHECK(tp2.calculate_specialization_match(tp1) > 1);
|
||||||
|
CHECK(tp1.calculate_specialization_match(tp2) == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
using clanguml::common::model::context;
|
||||||
|
using clanguml::common::model::rpqualifier;
|
||||||
|
|
||||||
|
auto tp1 = template_parameter::make_template_type({});
|
||||||
|
tp1.is_array(true);
|
||||||
|
tp1.add_template_param(template_parameter::make_template_type("int"));
|
||||||
|
tp1.add_template_param(template_parameter::make_template_type("N"));
|
||||||
|
|
||||||
|
CHECK(tp1.to_string({}, false) == "int[N]");
|
||||||
|
CHECK(tp1.is_specialization());
|
||||||
|
|
||||||
|
auto tp2 = template_parameter::make_argument({});
|
||||||
|
tp2.is_array(true);
|
||||||
|
tp2.add_template_param(template_parameter::make_argument("int"));
|
||||||
|
tp2.add_template_param(template_parameter::make_argument("1000"));
|
||||||
|
|
||||||
|
CHECK(tp2.to_string({}, false) == "int[1000]");
|
||||||
|
CHECK(tp2.is_specialization());
|
||||||
|
|
||||||
|
CHECK(tp2.calculate_specialization_match(tp1) > 1);
|
||||||
|
CHECK(tp1.calculate_specialization_match(tp2) == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
using clanguml::common::model::context;
|
||||||
|
using clanguml::common::model::rpqualifier;
|
||||||
|
|
||||||
|
auto tp1 = template_parameter::make_template_type("T");
|
||||||
|
tp1.push_context(context{.pr = rpqualifier::kLValueReference});
|
||||||
|
CHECK(tp1.is_specialization());
|
||||||
|
CHECK(tp1.to_string({}, false) == "T &");
|
||||||
|
|
||||||
|
auto tp2 = template_parameter::make_template_type({});
|
||||||
|
tp2.is_array(true);
|
||||||
|
tp2.add_template_param(template_parameter::make_template_type("int"));
|
||||||
|
tp2.add_template_param(template_parameter::make_template_type("N"));
|
||||||
|
|
||||||
|
CHECK(tp2.is_specialization());
|
||||||
|
CHECK(tp2.to_string({}, false) == "int[N]");
|
||||||
|
|
||||||
|
CHECK(tp2.calculate_specialization_match(tp1) == 0);
|
||||||
|
CHECK(tp1.calculate_specialization_match(tp2) == 0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user