diff --git a/breathe/renderer/filter.py b/breathe/renderer/filter.py index 0f071f492..1c65f52c3 100644 --- a/breathe/renderer/filter.py +++ b/breathe/renderer/filter.py @@ -480,7 +480,12 @@ def allow(self, node_stack) -> bool: name = self.name_accessor(node_stack) try: - namespace, name = name.rsplit("::", 1) + # strip out any template arguments before splitting on '::', to + # avoid errors if a template specialization has qualified arguments + # (see examples/specific/cpp_ns_template_specialization) + cleaned_name, sep, rest = name.partition("<") + namespace, name = cleaned_name.rsplit("::", 1) + name += sep + rest except ValueError: namespace, name = "", name diff --git a/breathe/renderer/sphinxrenderer.py b/breathe/renderer/sphinxrenderer.py index b12fac0f2..4c1258fce 100644 --- a/breathe/renderer/sphinxrenderer.py +++ b/breathe/renderer/sphinxrenderer.py @@ -1025,12 +1025,15 @@ def visit_class(self, node) -> list[Node]: # Defer to domains specific directive. names = self.get_qualification() - # TODO: this breaks if it's a template specialization - # and one of the arguments contain '::' + # strip out any template arguments before splitting on '::', to + # avoid errors if a template specialization has qualified arguments + # (see examples/specific/cpp_ns_template_specialization) + cleaned_name, sep, rest = nodeDef.compoundname.partition("<") if self.nesting_level == 0: - names.extend(nodeDef.compoundname.split("::")) + names.extend(cleaned_name.split("::")) else: - names.append(nodeDef.compoundname.split("::")[-1]) + names.append(cleaned_name.split("::")[-1]) + names[-1] += sep + rest decls = [ self.create_template_prefix(nodeDef), self.join_nested_name(names), diff --git a/documentation/source/conf.py b/documentation/source/conf.py index 3bb73d2f6..b14b69d54 100644 --- a/documentation/source/conf.py +++ b/documentation/source/conf.py @@ -221,6 +221,7 @@ "cpp_function_lookup": "../../examples/specific/cpp_function_lookup/xml/", "cpp_friendclass": "../../examples/specific/cpp_friendclass/xml/", "cpp_inherited_members": "../../examples/specific/cpp_inherited_members/xml/", + "cpp_ns_template_specialization": "../../examples/specific/cpp_ns_template_specialization/xml/", "cpp_trailing_return_type": "../../examples/specific/cpp_trailing_return_type/xml/", "cpp_constexpr_hax": "../../examples/specific/cpp_constexpr_hax/xml/", "xrefsect": "../../examples/specific/xrefsect/xml/", diff --git a/documentation/source/specific.rst b/documentation/source/specific.rst index f39126709..39c00db83 100644 --- a/documentation/source/specific.rst +++ b/documentation/source/specific.rst @@ -239,6 +239,14 @@ C++ Inherited Members .. doxygenclass:: B :project: cpp_inherited_members +C++ Template Specialization with Namespace +------------------------------------------ + +.. cpp:namespace:: @ex_specific_cpp_ns_template_specialization + +.. doxygenfile:: cpp_ns_template_specialization.h + :project: cpp_ns_template_specialization + C++ Trailing Return Type ------------------------ diff --git a/examples/specific/Makefile b/examples/specific/Makefile index 91941d5bf..22ed568e1 100644 --- a/examples/specific/Makefile +++ b/examples/specific/Makefile @@ -26,7 +26,7 @@ projects = nutshell alias rst inline namespacefile array inheritance \ enum define interface xrefsect tables \ cpp_anon cpp_concept cpp_enum cpp_union cpp_function cpp_friendclass \ cpp_inherited_members cpp_trailing_return_type cpp_constexpr_hax \ - cpp_function_lookup \ + cpp_function_lookup cpp_ns_template_specialization \ c_file c_struct c_enum c_typedef c_macro c_union membergroups \ simplesect code_blocks dot_graphs diff --git a/examples/specific/cpp_ns_template_specialization.cfg b/examples/specific/cpp_ns_template_specialization.cfg new file mode 100644 index 000000000..c9cd9ad05 --- /dev/null +++ b/examples/specific/cpp_ns_template_specialization.cfg @@ -0,0 +1,13 @@ +PROJECT_NAME = "C++ Template Specialization with Namespace" +OUTPUT_DIRECTORY = cpp_ns_template_specialization +GENERATE_LATEX = NO +GENERATE_MAN = NO +GENERATE_RTF = NO +CASE_SENSE_NAMES = NO +INPUT = cpp_ns_template_specialization.h +QUIET = YES +JAVADOC_AUTOBRIEF = YES +GENERATE_HTML = NO +GENERATE_XML = YES + +WARN_IF_UNDOCUMENTED = NO diff --git a/examples/specific/cpp_ns_template_specialization.h b/examples/specific/cpp_ns_template_specialization.h new file mode 100644 index 000000000..b944ee797 --- /dev/null +++ b/examples/specific/cpp_ns_template_specialization.h @@ -0,0 +1,15 @@ +namespace ns1 { +struct Foo { + int value; +}; +} // namespace ns1 + +namespace ns2 { +template struct Trait { + static constexpr bool valid = false; +}; + +template <> struct Trait { + static constexpr bool valid = true; +}; +} // namespace ns2