Skip to content

Commit

Permalink
Added support for template deduction guides
Browse files Browse the repository at this point in the history
  • Loading branch information
justinboswell committed Dec 1, 2023
1 parent f1708bf commit a667894
Show file tree
Hide file tree
Showing 2 changed files with 162 additions and 0 deletions.
59 changes: 59 additions & 0 deletions cxxheaderparser/parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -2563,6 +2563,54 @@ def _parse_operator_conversion(

_class_enum_stage2 = {":", "final", "explicit", "{"}

def _maybe_parse_deduction_guide(
self,
parsed_type: Type,
mods: ParsedTypeModifiers,
doxygen: typing.Optional[str],
template: TemplateDeclTypeVar,
location: Location,
) -> bool:
"""
Parses a deduction guide, e.g.
template <class T>
MyClass(T) -> MyClass(U);
"""

tok = self.lex.token_if("(")
if not tok:
return False

# scan past any possible parameters...
toks = self._consume_balanced_tokens(tok)
# ... and check to see if the next token is an arrow, and thus a trailing return
if not self.lex.token_peek_if("ARROW"):
self.lex.return_tokens(toks)
return False

# return the function params so they can be parsed properly, leaving out the leading ( as
# _parse_function expects that to have already been consumed
self.lex.return_tokens(toks[1:])

# use auto as the return type, which will force parsing of trailing return type
return_type = Type(PQName([AutoSpecifier()]))
pqname = parsed_type.typename
msvc_convention = self.lex.token_if_val(*self._msvc_conventions)
return self._parse_function(
mods,
return_type,
pqname,
None,
template,
doxygen,
location,
False,
False,
False,
False,
msvc_convention,
)

def _parse_declarations(
self,
tok: LexToken,
Expand Down Expand Up @@ -2593,6 +2641,17 @@ def _parse_declarations(
):
return

# check to see if this is a class template deduction guide
if (
parsed_type is not None
and not is_typedef
and not is_friend
and self._maybe_parse_deduction_guide(
parsed_type, mods, doxygen, template, location
)
):
return

var_ok = True

if is_typedef:
Expand Down
103 changes: 103 additions & 0 deletions tests/test_template.py
Original file line number Diff line number Diff line change
Expand Up @@ -2163,3 +2163,106 @@ def test_member_class_template_specialization() -> None:
]
)
)


def test_template_deduction_guide() -> None:
content = """
template <class CharT, class Traits = std::char_traits<CharT>>
Error(std::basic_string_view<CharT, Traits>) -> Error<std::string>;
"""
data = parse_string(content, cleandoc=True)

assert data == ParsedData(
namespace=NamespaceScope(
functions=[
Function(
return_type=Type(
typename=PQName(
segments=[
NameSpecifier(
name="Error",
specialization=TemplateSpecialization(
args=[
TemplateArgument(
arg=Type(
typename=PQName(
segments=[
NameSpecifier(name="std"),
NameSpecifier(
name="string"
),
]
)
)
)
]
),
)
]
)
),
name=PQName(segments=[NameSpecifier(name="Error")]),
parameters=[
Parameter(
type=Type(
typename=PQName(
segments=[
NameSpecifier(name="std"),
NameSpecifier(
name="basic_string_view",
specialization=TemplateSpecialization(
args=[
TemplateArgument(
arg=Type(
typename=PQName(
segments=[
NameSpecifier(
name="CharT"
)
]
)
)
),
TemplateArgument(
arg=Type(
typename=PQName(
segments=[
NameSpecifier(
name="Traits"
)
]
)
)
),
]
),
),
]
)
)
)
],
has_trailing_return=True,
template=TemplateDecl(
params=[
TemplateTypeParam(typekey="class", name="CharT"),
TemplateTypeParam(
typekey="class",
name="Traits",
default=Value(
tokens=[
Token(value="std"),
Token(value="::"),
Token(value="char_traits"),
Token(value="<"),
Token(value="CharT"),
Token(value=">"),
]
),
),
]
),
)
]
)
)

0 comments on commit a667894

Please sign in to comment.