Refactored template specialization matching
This commit is contained in:
@@ -109,84 +109,36 @@ void template_parameter::is_variadic(bool is_variadic) noexcept
|
||||
bool template_parameter::is_variadic() const noexcept { return is_variadic_; }
|
||||
|
||||
int template_parameter::calculate_specialization_match(
|
||||
const template_parameter &ct) const
|
||||
const template_parameter &base_template_parameter) const
|
||||
{
|
||||
int res{0};
|
||||
|
||||
if (ct.type().has_value() && type().has_value() &&
|
||||
!ct.is_template_parameter() && !is_template_parameter()) {
|
||||
if (base_template_parameter.type().has_value() && type().has_value() &&
|
||||
!base_template_parameter.is_template_parameter() &&
|
||||
!is_template_parameter()) {
|
||||
|
||||
if (ct.type().value() != type().value())
|
||||
if (base_template_parameter.type().value() != type().value())
|
||||
return 0;
|
||||
else
|
||||
res++;
|
||||
}
|
||||
|
||||
if (ct.is_function_template() && !is_function_template())
|
||||
if (base_template_parameter.is_function_template() &&
|
||||
!is_function_template())
|
||||
return 0;
|
||||
|
||||
if (template_params().size() > 0 && ct.template_params().size() > 0) {
|
||||
// More generic template params
|
||||
const auto &template_params = ct.template_params();
|
||||
const auto &specialization_params = this->template_params();
|
||||
auto template_index{0U};
|
||||
auto arg_index{0U};
|
||||
if (!base_template_parameter.template_params().empty() &&
|
||||
!template_params().empty()) {
|
||||
auto params_match = calculate_template_params_specialization_match(
|
||||
template_params(), base_template_parameter.template_params());
|
||||
|
||||
while (arg_index < specialization_params.size() &&
|
||||
template_index < template_params.size()) {
|
||||
auto match = specialization_params.at(arg_index)
|
||||
.calculate_specialization_match(
|
||||
template_params.at(template_index));
|
||||
|
||||
if (match == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!template_params.at(template_index).is_variadic())
|
||||
template_index++;
|
||||
|
||||
res += match;
|
||||
|
||||
// Add 1 point if the current specialization param is an argument
|
||||
// as it's a more specific match than 2 template params
|
||||
if (!specialization_params.at(arg_index).is_template_parameter())
|
||||
res++;
|
||||
|
||||
arg_index++;
|
||||
}
|
||||
|
||||
if (arg_index == specialization_params.size()) {
|
||||
// Check also backwards to make sure that trailing non-variadic
|
||||
// params match after a variadic parameter
|
||||
template_index = template_params.size() - 1;
|
||||
arg_index = specialization_params.size() - 1;
|
||||
|
||||
while (true) {
|
||||
auto match = specialization_params.at(arg_index)
|
||||
.calculate_specialization_match(
|
||||
template_params.at(template_index));
|
||||
if (match == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (arg_index == 0 || template_index == 0)
|
||||
break;
|
||||
|
||||
arg_index--;
|
||||
|
||||
if (!template_params.at(template_index).is_variadic())
|
||||
template_index--;
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
else
|
||||
if (params_match == 0)
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ((ct.is_template_parameter() || ct.is_template_template_parameter()) &&
|
||||
res += params_match;
|
||||
}
|
||||
else if ((base_template_parameter.is_template_parameter() ||
|
||||
base_template_parameter.is_template_template_parameter()) &&
|
||||
!is_template_parameter())
|
||||
return 1;
|
||||
|
||||
@@ -372,4 +324,76 @@ const std::optional<std::string> &template_parameter::concept_constraint() const
|
||||
return concept_constraint_;
|
||||
}
|
||||
|
||||
int calculate_template_params_specialization_match(
|
||||
const std::vector<template_parameter> &specialization_params,
|
||||
const std::vector<template_parameter> &template_params)
|
||||
{
|
||||
int res{0};
|
||||
|
||||
if (!specialization_params.empty() && !template_params.empty()) {
|
||||
auto template_index{0U};
|
||||
auto arg_index{0U};
|
||||
|
||||
while (arg_index < specialization_params.size() &&
|
||||
template_index < template_params.size()) {
|
||||
auto match = specialization_params.at(arg_index)
|
||||
.calculate_specialization_match(
|
||||
template_params.at(template_index));
|
||||
|
||||
if (match == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Add 1 point if the current specialization param is an argument
|
||||
// as it's a more specific match than 2 template params
|
||||
if (!specialization_params.at(arg_index).is_template_parameter())
|
||||
res++;
|
||||
|
||||
// Add 1 point if the current template param is an argument
|
||||
// as it's a more specific match than 2 template params
|
||||
if (!template_params.at(template_index).is_template_parameter())
|
||||
res++;
|
||||
|
||||
if (!template_params.at(template_index).is_variadic())
|
||||
template_index++;
|
||||
|
||||
res += match;
|
||||
|
||||
arg_index++;
|
||||
}
|
||||
|
||||
if (arg_index == specialization_params.size()) {
|
||||
// Check also backwards to make sure that trailing non-variadic
|
||||
// params match after a variadic parameter
|
||||
template_index = template_params.size() - 1;
|
||||
arg_index = specialization_params.size() - 1;
|
||||
|
||||
while (true) {
|
||||
auto match = specialization_params.at(arg_index)
|
||||
.calculate_specialization_match(
|
||||
template_params.at(template_index));
|
||||
if (match == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (arg_index == 0 || template_index == 0)
|
||||
break;
|
||||
|
||||
arg_index--;
|
||||
|
||||
if (!template_params.at(template_index).is_variadic())
|
||||
template_index--;
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
} // namespace clanguml::common::model
|
||||
|
||||
@@ -122,7 +122,8 @@ public:
|
||||
void is_variadic(bool is_variadic) noexcept;
|
||||
bool is_variadic() const noexcept;
|
||||
|
||||
int calculate_specialization_match(const template_parameter &ct) const;
|
||||
int calculate_specialization_match(
|
||||
const template_parameter &base_template_parameter) const;
|
||||
|
||||
friend bool operator==(
|
||||
const template_parameter &l, const template_parameter &r);
|
||||
@@ -221,4 +222,9 @@ private:
|
||||
|
||||
bool is_unexposed_{false};
|
||||
};
|
||||
|
||||
int calculate_template_params_specialization_match(
|
||||
const std::vector<template_parameter> &specialization,
|
||||
const std::vector<template_parameter> &base_template);
|
||||
|
||||
} // namespace clanguml::common::model
|
||||
|
||||
@@ -58,42 +58,16 @@ bool template_trait::is_implicit() const { return is_implicit_; }
|
||||
|
||||
void template_trait::set_implicit(bool implicit) { is_implicit_ = implicit; }
|
||||
|
||||
const std::vector<template_parameter> &template_trait::templates() const
|
||||
const std::vector<template_parameter> &template_trait::template_params() const
|
||||
{
|
||||
return templates_;
|
||||
}
|
||||
|
||||
int template_trait::calculate_template_specialization_match(
|
||||
const template_trait &other) const
|
||||
const template_trait &base_template) const
|
||||
{
|
||||
int res{0};
|
||||
|
||||
// Iterate over all template arguments
|
||||
for (auto i = 0U; i < other.templates().size(); i++) {
|
||||
const auto &template_arg = templates().at(i);
|
||||
const auto &other_template_arg = other.templates().at(i);
|
||||
|
||||
if (template_arg == other_template_arg) {
|
||||
res++;
|
||||
|
||||
if (!template_arg.is_template_parameter())
|
||||
res++;
|
||||
|
||||
if (!other_template_arg.is_template_parameter())
|
||||
res++;
|
||||
}
|
||||
else if (auto match = other_template_arg.calculate_specialization_match(
|
||||
template_arg);
|
||||
match > 0) {
|
||||
res += match;
|
||||
}
|
||||
else {
|
||||
res = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return res;
|
||||
return calculate_template_params_specialization_match(
|
||||
template_params(), base_template.template_params());
|
||||
}
|
||||
|
||||
} // namespace clanguml::common::model
|
||||
@@ -36,7 +36,7 @@ public:
|
||||
|
||||
void add_template(template_parameter &&tmplt);
|
||||
|
||||
const std::vector<template_parameter> &templates() const;
|
||||
const std::vector<template_parameter> &template_params() const;
|
||||
|
||||
int calculate_template_specialization_match(
|
||||
const template_trait &other) const;
|
||||
|
||||
Reference in New Issue
Block a user