From 2b951fe1708a9d458f8fe0e3844717a95b5864dd Mon Sep 17 00:00:00 2001 From: Bartek Kryza Date: Wed, 5 Apr 2023 00:44:27 +0200 Subject: [PATCH] Fixed matching template instantiation to templates with variadic params in the middle --- src/common/model/template_parameter.cc | 42 ++++++++++++++++++++++---- tests/test_model.cc | 14 +++++++++ 2 files changed, 50 insertions(+), 6 deletions(-) diff --git a/src/common/model/template_parameter.cc b/src/common/model/template_parameter.cc index 166b3b06..39f84b4a 100644 --- a/src/common/model/template_parameter.cc +++ b/src/common/model/template_parameter.cc @@ -114,9 +114,13 @@ int template_parameter::calculate_specialization_match( int res{0}; if (ct.type().has_value() && type().has_value() && - !ct.is_template_parameter() && !is_template_parameter() && - ct.type().value() != type().value()) - return 0; + !ct.is_template_parameter() && !is_template_parameter()) { + + if (ct.type().value() != type().value()) + return 0; + else + res++; + } if (ct.is_function_template() && !is_function_template()) return 0; @@ -143,15 +147,41 @@ int template_parameter::calculate_specialization_match( res += match; - // Add 1 point for argument 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()) + 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; } @@ -160,7 +190,7 @@ int template_parameter::calculate_specialization_match( !is_template_parameter()) return 1; - return 0; + return res; } void template_parameter::add_template_param(template_parameter &&ct) diff --git a/tests/test_model.cc b/tests/test_model.cc index b234a78a..49611605 100644 --- a/tests/test_model.cc +++ b/tests/test_model.cc @@ -125,6 +125,20 @@ TEST_CASE( CHECK(tp2.calculate_specialization_match(tp1)); } + { + auto tp1 = template_parameter::make_argument("tuple"); + tp1.add_template_param( + template_parameter::make_template_type("Args", {}, true)); + tp1.add_template_param(template_parameter::make_argument("int")); + + auto tp2 = template_parameter::make_argument("tuple"); + tp2.add_template_param(template_parameter::make_argument("char")); + tp2.add_template_param(template_parameter::make_argument("double")); + tp2.add_template_param(template_parameter::make_argument("int")); + + CHECK(tp2.calculate_specialization_match(tp1)); + } + { auto tp1 = template_parameter::make_argument("tuple"); tp1.add_template_param(