# Note: testcases generated via `python -m cxxheaderparser.gentest` from cxxheaderparser.types import ( Array, BaseClass, ClassDecl, DecltypeSpecifier, Field, ForwardDecl, Function, FunctionType, FundamentalSpecifier, Method, NameSpecifier, PQName, Parameter, Pointer, Reference, TemplateArgument, TemplateDecl, TemplateInst, TemplateNonTypeParam, TemplateSpecialization, TemplateTypeParam, Token, Type, Value, Variable, ) from cxxheaderparser.simple import ClassScope, NamespaceScope, ParsedData, parse_string def test_template_base_template_ns() -> None: content = """ class A : public B::C {}; """ data = parse_string(content, cleandoc=True) assert data == ParsedData( namespace=NamespaceScope( classes=[ ClassScope( class_decl=ClassDecl( typename=PQName( segments=[NameSpecifier(name="A")], classkey="class" ), bases=[ BaseClass( access="public", typename=PQName( segments=[ NameSpecifier( name="B", specialization=TemplateSpecialization( args=[ TemplateArgument( arg=Type( typename=PQName( segments=[ FundamentalSpecifier( name="int" ) ] ) ) ), TemplateArgument( arg=Type( typename=PQName( segments=[ FundamentalSpecifier( name="int" ) ] ) ) ), ] ), ), NameSpecifier(name="C"), ] ), ) ], ) ) ] ) ) def test_template_non_type_various() -> None: content = """ // simple non-type template parameter template struct S { int a[N]; }; template struct S2 {}; // complicated non-type example template struct Complicated { // calls the function selected at compile time // and stores the result in the array selected at compile time void foo(char base) { ra[4] = pf(c - base); } }; """ data = parse_string(content, cleandoc=True) assert data == ParsedData( namespace=NamespaceScope( classes=[ ClassScope( class_decl=ClassDecl( typename=PQName( segments=[NameSpecifier(name="S")], classkey="struct" ), template=TemplateDecl( params=[ TemplateNonTypeParam( type=Type( typename=PQName( segments=[FundamentalSpecifier(name="int")] ) ), name="N", ) ] ), ), fields=[ Field( name="a", type=Array( array_of=Type( typename=PQName( segments=[FundamentalSpecifier(name="int")] ) ), size=Value(tokens=[Token(value="N")]), ), access="public", ) ], ), ClassScope( class_decl=ClassDecl( typename=PQName( segments=[NameSpecifier(name="S2")], classkey="struct" ), template=TemplateDecl( params=[ TemplateNonTypeParam( type=Pointer( ptr_to=Type( typename=PQName( segments=[ FundamentalSpecifier(name="char") ] ), const=True, ) ) ) ] ), ) ), ClassScope( class_decl=ClassDecl( typename=PQName( segments=[NameSpecifier(name="Complicated")], classkey="struct", ), template=TemplateDecl( params=[ TemplateNonTypeParam( type=Type( typename=PQName( segments=[FundamentalSpecifier(name="char")] ) ), name="c", ), TemplateNonTypeParam( type=Reference( ref_to=Array( array_of=Type( typename=PQName( segments=[ FundamentalSpecifier(name="int") ] ) ), size=Value(tokens=[Token(value="5")]), ) ), name="ra", ), TemplateNonTypeParam( type=Pointer( ptr_to=FunctionType( return_type=Type( typename=PQName( segments=[ FundamentalSpecifier(name="int") ] ) ), parameters=[ Parameter( type=Type( typename=PQName( segments=[ FundamentalSpecifier( name="int" ) ] ) ) ) ], ) ), name="pf", ), ] ), ), methods=[ Method( return_type=Type( typename=PQName( segments=[FundamentalSpecifier(name="void")] ) ), name=PQName(segments=[NameSpecifier(name="foo")]), parameters=[ Parameter( type=Type( typename=PQName( segments=[FundamentalSpecifier(name="char")] ) ), name="base", ) ], has_body=True, access="public", ) ], ), ] ) ) def test_template_dependent_nontype_default() -> None: content = """ template class X; """ data = parse_string(content, cleandoc=True) assert data == ParsedData( namespace=NamespaceScope( forward_decls=[ ForwardDecl( typename=PQName( segments=[NameSpecifier(name="X")], classkey="class" ), template=TemplateDecl( params=[ TemplateTypeParam(typekey="class", name="T"), TemplateNonTypeParam( type=Type( typename=PQName( segments=[ NameSpecifier(name="T"), NameSpecifier(name="type"), ] ) ), name="n", default=Value(tokens=[Token(value="0")]), ), ] ), ) ] ) ) def test_template_optional_names() -> None: content = """ template class My_vector; template struct My_op_functor; template class My_tuple; """ data = parse_string(content, cleandoc=True) assert data == ParsedData( namespace=NamespaceScope( forward_decls=[ ForwardDecl( typename=PQName( segments=[NameSpecifier(name="My_vector")], classkey="class" ), template=TemplateDecl(params=[TemplateTypeParam(typekey="class")]), ), ForwardDecl( typename=PQName( segments=[NameSpecifier(name="My_op_functor")], classkey="struct", ), template=TemplateDecl( params=[ TemplateTypeParam( typekey="class", default=Value(tokens=[Token(value="void")]), ) ] ), ), ForwardDecl( typename=PQName( segments=[NameSpecifier(name="My_tuple")], classkey="class" ), template=TemplateDecl( params=[TemplateTypeParam(typekey="typename", param_pack=True)] ), ), ] ) ) def test_template_template_template() -> None: content = """ template struct eval; // primary template template class TT, typename T1, typename... Rest> struct eval> {}; // partial specialization of eval """ data = parse_string(content, cleandoc=True) assert data == ParsedData( namespace=NamespaceScope( classes=[ ClassScope( class_decl=ClassDecl( typename=PQName( segments=[ NameSpecifier( name="eval", specialization=TemplateSpecialization( args=[ TemplateArgument( arg=Type( typename=PQName( segments=[ NameSpecifier( name="TT", specialization=TemplateSpecialization( args=[ TemplateArgument( arg=Type( typename=PQName( segments=[ NameSpecifier( name="T1" ) ] ) ) ), TemplateArgument( arg=Type( typename=PQName( segments=[ NameSpecifier( name="Rest" ) ] ) ), param_pack=True, ), ] ), ) ] ) ) ) ] ), ) ], classkey="struct", ), template=TemplateDecl( params=[ TemplateTypeParam( typekey="class", name="TT", template=TemplateDecl( params=[ TemplateTypeParam(typekey="typename"), TemplateTypeParam( typekey="typename", param_pack=True ), ] ), ), TemplateTypeParam(typekey="typename", name="T1"), TemplateTypeParam( typekey="typename", name="Rest", param_pack=True ), ] ), ) ) ], forward_decls=[ ForwardDecl( typename=PQName( segments=[NameSpecifier(name="eval")], classkey="struct" ), template=TemplateDecl( params=[TemplateTypeParam(typekey="typename", name="T")] ), ) ], ) ) def test_template_static_var() -> None: content = """ template struct X { static int x; }; template int X::x = 5; """ data = parse_string(content, cleandoc=True) assert data == ParsedData( namespace=NamespaceScope( classes=[ ClassScope( class_decl=ClassDecl( typename=PQName( segments=[NameSpecifier(name="X")], classkey="struct" ), template=TemplateDecl( params=[TemplateTypeParam(typekey="typename", name="T")] ), ), fields=[ Field( access="public", type=Type( typename=PQName( segments=[FundamentalSpecifier(name="int")] ) ), name="x", static=True, ) ], ) ], variables=[ Variable( name=PQName( segments=[ NameSpecifier( name="X", specialization=TemplateSpecialization( args=[ TemplateArgument( arg=Type( typename=PQName( segments=[NameSpecifier(name="T")] ) ) ) ] ), ), NameSpecifier(name="x"), ] ), type=Type( typename=PQName(segments=[FundamentalSpecifier(name="int")]) ), value=Value(tokens=[Token(value="5")]), template=TemplateDecl( params=[TemplateTypeParam(typekey="typename", name="T")] ), ) ], ) ) def test_template_fn_template() -> None: content = """ class S { template StringRef copy(Allocator &A) const { // Don't request a length 0 copy from the allocator. if (empty()) return StringRef(); char *S = A.template Allocate(Length); std::copy(begin(), end(), S); return StringRef(S, Length); } }; """ data = parse_string(content, cleandoc=True) assert data == ParsedData( namespace=NamespaceScope( classes=[ ClassScope( class_decl=ClassDecl( typename=PQName( segments=[NameSpecifier(name="S")], classkey="class" ) ), methods=[ Method( return_type=Type( typename=PQName( segments=[NameSpecifier(name="StringRef")] ) ), name=PQName(segments=[NameSpecifier(name="copy")]), parameters=[ Parameter( type=Reference( ref_to=Type( typename=PQName( segments=[ NameSpecifier(name="Allocator") ] ) ) ), name="A", ) ], has_body=True, template=TemplateDecl( params=[ TemplateTypeParam( typekey="typename", name="Allocator" ) ] ), access="private", const=True, ) ], ) ] ) ) def test_template_fn_param_initializer() -> None: content = """ template void fn(something s = something{1, 2, 3}); """ data = parse_string(content, cleandoc=True) assert data == ParsedData( namespace=NamespaceScope( functions=[ Function( return_type=Type( typename=PQName(segments=[FundamentalSpecifier(name="void")]) ), name=PQName(segments=[NameSpecifier(name="fn")]), parameters=[ Parameter( type=Type( typename=PQName( segments=[ NameSpecifier( name="something", specialization=TemplateSpecialization( args=[ TemplateArgument( arg=Type( typename=PQName( segments=[ NameSpecifier( name="T" ) ] ) ) ), TemplateArgument( arg=Type( typename=PQName( segments=[ NameSpecifier( name="U" ) ] ) ) ), ] ), ) ] ) ), name="s", default=Value( tokens=[ Token(value="something"), Token(value="<"), Token(value="T"), Token(value=","), Token(value="U"), Token(value=">"), Token(value="{"), Token(value="1"), Token(value=","), Token(value="2"), Token(value=","), Token(value="3"), Token(value="}"), ] ), ) ], template=TemplateDecl( params=[ TemplateTypeParam(typekey="typename", name="T"), TemplateTypeParam(typekey="typename", name="U"), ] ), ) ] ) ) def test_template_huge() -> None: content = """ // clang-format off class AlmondClass { public: std::map > > meth(bool flag, std::map > > bigArg); }; """ data = parse_string(content, cleandoc=True) assert data == ParsedData( namespace=NamespaceScope( classes=[ ClassScope( class_decl=ClassDecl( typename=PQName( segments=[NameSpecifier(name="AlmondClass")], classkey="class", ) ), methods=[ Method( return_type=Type( typename=PQName( segments=[ NameSpecifier(name="std"), NameSpecifier( name="map", specialization=TemplateSpecialization( args=[ TemplateArgument( arg=Type( typename=PQName( segments=[ FundamentalSpecifier( name="unsigned" ) ] ) ) ), TemplateArgument( arg=Type( typename=PQName( segments=[ NameSpecifier( name="std" ), NameSpecifier( name="pair", specialization=TemplateSpecialization( args=[ TemplateArgument( arg=Type( typename=PQName( segments=[ FundamentalSpecifier( name="unsigned" ) ] ) ) ), TemplateArgument( arg=Type( typename=PQName( segments=[ NameSpecifier( name="SnailTemplateClass", specialization=TemplateSpecialization( args=[ TemplateArgument( arg=Type( typename=PQName( segments=[ NameSpecifier( name="SnailNamespace" ), NameSpecifier( name="SnailClass" ), ] ) ) ) ] ), ) ] ) ) ), ] ), ), ] ) ) ), ] ), ), ] ) ), name=PQName(segments=[NameSpecifier(name="meth")]), parameters=[ Parameter( type=Type( typename=PQName( segments=[FundamentalSpecifier(name="bool")] ) ), name="flag", ), Parameter( type=Type( typename=PQName( segments=[ NameSpecifier(name="std"), NameSpecifier( name="map", specialization=TemplateSpecialization( args=[ TemplateArgument( arg=Type( typename=PQName( segments=[ FundamentalSpecifier( name="unsigned" ) ] ) ) ), TemplateArgument( arg=Type( typename=PQName( segments=[ NameSpecifier( name="std" ), NameSpecifier( name="pair", specialization=TemplateSpecialization( args=[ TemplateArgument( arg=Type( typename=PQName( segments=[ FundamentalSpecifier( name="unsigned" ) ] ) ) ), TemplateArgument( arg=Type( typename=PQName( segments=[ NameSpecifier( name="SnailTemplateClass", specialization=TemplateSpecialization( args=[ TemplateArgument( arg=Type( typename=PQName( segments=[ NameSpecifier( name="SnailNamespace" ), NameSpecifier( name="SnailClass" ), ] ) ) ) ] ), ) ] ) ) ), ] ), ), ] ) ) ), ] ), ), ] ) ), name="bigArg", ), ], access="public", ) ], ) ] ) ) def test_template_specialized() -> None: content = """ template <> class FruitFly : public Fly {}; """ data = parse_string(content, cleandoc=True) assert data == ParsedData( namespace=NamespaceScope( classes=[ ClassScope( class_decl=ClassDecl( typename=PQName( segments=[ NameSpecifier( name="FruitFly", specialization=TemplateSpecialization( args=[ TemplateArgument( arg=Type( typename=PQName( segments=[ FundamentalSpecifier( name="int" ) ] ) ) ) ] ), ) ], classkey="class", ), bases=[ BaseClass( access="public", typename=PQName(segments=[NameSpecifier(name="Fly")]), ) ], template=TemplateDecl(), ) ) ] ) ) def test_template_class_defaults() -> None: content = """ template > class Raddish_SetIterator : public Raddish_Iterator { protected: VALUE_SET_ITERATOR _beg, _end; public: Raddish_SetIterator(const VALUE_SET_ITERATOR &begin, const VALUE_SET_ITERATOR &end) { init(begin, end); } }; """ data = parse_string(content, cleandoc=True) assert data == ParsedData( namespace=NamespaceScope( classes=[ ClassScope( class_decl=ClassDecl( typename=PQName( segments=[NameSpecifier(name="Raddish_SetIterator")], classkey="class", ), bases=[ BaseClass( access="public", typename=PQName( segments=[ NameSpecifier( name="Raddish_Iterator", specialization=TemplateSpecialization( args=[ TemplateArgument( arg=Type( typename=PQName( segments=[ NameSpecifier( name="VALUE" ) ] ) ) ) ] ), ) ] ), ) ], template=TemplateDecl( params=[ TemplateTypeParam(typekey="typename", name="VALUE"), TemplateTypeParam( typekey="typename", name="VALUE_SET_ITERATOR" ), TemplateTypeParam( typekey="typename", name="ACCESSOR", default=Value( tokens=[ Token(value="Raddish"), Token(value="::"), Token(value="SimpleAccessor"), Token(value="<"), Token(value="VALUE"), Token(value=","), Token(value="VALUE_SET_ITERATOR"), Token(value=">"), ] ), ), ] ), ), fields=[ Field( access="protected", type=Type( typename=PQName( segments=[NameSpecifier(name="VALUE_SET_ITERATOR")] ) ), name="_beg", ), Field( access="protected", type=Type( typename=PQName( segments=[NameSpecifier(name="VALUE_SET_ITERATOR")] ) ), name="_end", ), ], methods=[ Method( return_type=None, name=PQName( segments=[NameSpecifier(name="Raddish_SetIterator")] ), parameters=[ Parameter( type=Reference( ref_to=Type( typename=PQName( segments=[ NameSpecifier( name="VALUE_SET_ITERATOR" ) ] ), const=True, ) ), name="begin", ), Parameter( type=Reference( ref_to=Type( typename=PQName( segments=[ NameSpecifier( name="VALUE_SET_ITERATOR" ) ] ), const=True, ) ), name="end", ), ], has_body=True, access="public", constructor=True, ) ], ) ] ) ) def test_template_many_packs() -> None: content = """ // clang-format off template class XYZ : public MyBaseClass { public: XYZ(); }; template class concat_iterator : public iterator_facade_base, std::forward_iterator_tag, ValueT> { }; template struct build_index_impl : build_index_impl {}; template struct build_index_impl<0, I...> : index_sequence {}; template struct is_callable, void_t()).*std::declval())(std::declval()...))>> : std::true_type {}; template struct S : public T... {}; """ data = parse_string(content, cleandoc=True) assert data == ParsedData( namespace=NamespaceScope( classes=[ ClassScope( class_decl=ClassDecl( typename=PQName( segments=[NameSpecifier(name="XYZ")], classkey="class" ), bases=[ BaseClass( access="public", typename=PQName( segments=[ NameSpecifier( name="MyBaseClass", specialization=TemplateSpecialization( args=[ TemplateArgument( arg=Type( typename=PQName( segments=[ NameSpecifier( name="Type" ) ] ) ) ), TemplateArgument( arg=Type( typename=PQName( segments=[ FundamentalSpecifier( name="int" ) ] ) ) ), ] ), ) ] ), ) ], template=TemplateDecl( params=[TemplateTypeParam(typekey="typename", name="Type")] ), ), methods=[ Method( return_type=None, name=PQName(segments=[NameSpecifier(name="XYZ")]), parameters=[], access="public", constructor=True, ) ], ), ClassScope( class_decl=ClassDecl( typename=PQName( segments=[NameSpecifier(name="concat_iterator")], classkey="class", ), bases=[ BaseClass( access="public", typename=PQName( segments=[ NameSpecifier( name="iterator_facade_base", specialization=TemplateSpecialization( args=[ TemplateArgument( arg=Type( typename=PQName( segments=[ NameSpecifier( name="concat_iterator", specialization=TemplateSpecialization( args=[ TemplateArgument( arg=Type( typename=PQName( segments=[ NameSpecifier( name="ValueT" ) ] ) ) ), TemplateArgument( arg=Type( typename=PQName( segments=[ NameSpecifier( name="IterTs" ) ] ) ), param_pack=True, ), ] ), ) ] ) ) ), TemplateArgument( arg=Type( typename=PQName( segments=[ NameSpecifier( name="std" ), NameSpecifier( name="forward_iterator_tag" ), ] ) ) ), TemplateArgument( arg=Type( typename=PQName( segments=[ NameSpecifier( name="ValueT" ) ] ) ) ), ] ), ) ] ), ) ], template=TemplateDecl( params=[ TemplateTypeParam(typekey="typename", name="ValueT"), TemplateTypeParam( typekey="typename", name="IterTs", param_pack=True ), ] ), ) ), ClassScope( class_decl=ClassDecl( typename=PQName( segments=[NameSpecifier(name="build_index_impl")], classkey="struct", ), bases=[ BaseClass( access="public", typename=PQName( segments=[ NameSpecifier( name="build_index_impl", specialization=TemplateSpecialization( args=[ TemplateArgument( arg=Value( tokens=[ Token(value="N"), Token(value="-"), Token(value="1"), ] ) ), TemplateArgument( arg=Value( tokens=[ Token(value="N"), Token(value="-"), Token(value="1"), ] ) ), TemplateArgument( arg=Type( typename=PQName( segments=[ NameSpecifier( name="I" ) ] ) ), param_pack=True, ), ] ), ) ] ), ) ], template=TemplateDecl( params=[ TemplateNonTypeParam( type=Type( typename=PQName( segments=[ NameSpecifier(name="std"), NameSpecifier(name="size_t"), ] ) ), name="N", ), TemplateNonTypeParam( type=Type( typename=PQName( segments=[ NameSpecifier(name="std"), NameSpecifier(name="size_t"), ] ) ), name="I", param_pack=True, ), ] ), ) ), ClassScope( class_decl=ClassDecl( typename=PQName( segments=[ NameSpecifier( name="build_index_impl", specialization=TemplateSpecialization( args=[ TemplateArgument( arg=Value(tokens=[Token(value="0")]) ), TemplateArgument( arg=Type( typename=PQName( segments=[ NameSpecifier(name="I") ] ) ), param_pack=True, ), ] ), ) ], classkey="struct", ), bases=[ BaseClass( access="public", typename=PQName( segments=[ NameSpecifier( name="index_sequence", specialization=TemplateSpecialization( args=[ TemplateArgument( arg=Type( typename=PQName( segments=[ NameSpecifier( name="I" ) ] ) ), param_pack=True, ) ] ), ) ] ), ) ], template=TemplateDecl( params=[ TemplateNonTypeParam( type=Type( typename=PQName( segments=[ NameSpecifier(name="std"), NameSpecifier(name="size_t"), ] ) ), name="I", param_pack=True, ) ] ), ) ), ClassScope( class_decl=ClassDecl( typename=PQName( segments=[ NameSpecifier( name="is_callable", specialization=TemplateSpecialization( args=[ TemplateArgument( arg=Type( typename=PQName( segments=[ NameSpecifier(name="F") ] ) ) ), TemplateArgument( arg=Type( typename=PQName( segments=[ NameSpecifier(name="P") ] ) ) ), TemplateArgument( arg=Type( typename=PQName( segments=[ NameSpecifier( name="typelist", specialization=TemplateSpecialization( args=[ TemplateArgument( arg=Type( typename=PQName( segments=[ NameSpecifier( name="T" ) ] ) ), param_pack=True, ) ] ), ) ] ) ) ), TemplateArgument( arg=Type( typename=PQName( segments=[ NameSpecifier( name="void_t", specialization=TemplateSpecialization( args=[ TemplateArgument( arg=Type( typename=PQName( segments=[ DecltypeSpecifier( tokens=[ Token( value="(" ), Token( value="(" ), Token( value="*" ), Token( value="std" ), Token( value="::" ), Token( value="declval" ), Token( value="<" ), Token( value="P" ), Token( value=">" ), Token( value="(" ), Token( value=")" ), Token( value=")" ), Token( value="." ), Token( value="*" ), Token( value="std" ), Token( value="::" ), Token( value="declval" ), Token( value="<" ), Token( value="F" ), Token( value=">" ), Token( value="(" ), Token( value=")" ), Token( value=")" ), Token( value="(" ), Token( value="std" ), Token( value="::" ), Token( value="declval" ), Token( value="<" ), Token( value="T" ), Token( value=">" ), Token( value="(" ), Token( value=")" ), Token( value="..." ), Token( value=")" ), ] ) ] ) ) ) ] ), ) ] ) ) ), ] ), ) ], classkey="struct", ), bases=[ BaseClass( access="public", typename=PQName( segments=[ NameSpecifier(name="std"), NameSpecifier(name="true_type"), ] ), ) ], template=TemplateDecl( params=[ TemplateTypeParam(typekey="typename", name="F"), TemplateTypeParam(typekey="typename", name="P"), TemplateTypeParam( typekey="typename", name="T", param_pack=True ), ] ), ) ), ClassScope( class_decl=ClassDecl( typename=PQName( segments=[NameSpecifier(name="S")], classkey="struct" ), bases=[ BaseClass( access="public", typename=PQName(segments=[NameSpecifier(name="T")]), param_pack=True, ) ], template=TemplateDecl( params=[ TemplateNonTypeParam( type=Type( typename=PQName( segments=[NameSpecifier(name="T")] ) ), param_pack=True, ) ] ), ) ), ] ) ) def test_template_specialized_fn_typename() -> None: content = """ // clang-format off struct T{}; template class C { template<> void foo(); }; """ data = parse_string(content, cleandoc=True) assert data == ParsedData( namespace=NamespaceScope( classes=[ ClassScope( class_decl=ClassDecl( typename=PQName( segments=[NameSpecifier(name="T")], classkey="struct" ) ) ), ClassScope( class_decl=ClassDecl( typename=PQName( segments=[NameSpecifier(name="C")], classkey="class" ), template=TemplateDecl( params=[TemplateTypeParam(typekey="typename", name="T")] ), ), methods=[ Method( return_type=Type( typename=PQName( segments=[FundamentalSpecifier(name="void")] ) ), name=PQName( segments=[ NameSpecifier( name="foo", specialization=TemplateSpecialization( args=[ TemplateArgument( arg=Type( typename=PQName( segments=[ NameSpecifier(name=""), NameSpecifier(name="T"), ], has_typename=True, ) ), ) ] ), ) ] ), parameters=[], template=TemplateDecl(), access="private", ) ], ), ] ) ) def test_template_specialized_fn_typename_template() -> None: content = """ // clang-format off template struct T{}; template class C { template<> void foo>(); }; """ data = parse_string(content, cleandoc=True) assert data == ParsedData( namespace=NamespaceScope( classes=[ ClassScope( class_decl=ClassDecl( typename=PQName( segments=[NameSpecifier(name="T")], classkey="struct" ), template=TemplateDecl( params=[TemplateTypeParam(typekey="typename", name="X")] ), ) ), ClassScope( class_decl=ClassDecl( typename=PQName( segments=[NameSpecifier(name="C")], classkey="class" ), template=TemplateDecl( params=[TemplateTypeParam(typekey="typename", name="T")] ), ), methods=[ Method( return_type=Type( typename=PQName( segments=[FundamentalSpecifier(name="void")] ) ), name=PQName( segments=[ NameSpecifier( name="foo", specialization=TemplateSpecialization( args=[ TemplateArgument( arg=Type( typename=PQName( segments=[ NameSpecifier(name=""), NameSpecifier( name="T", specialization=TemplateSpecialization( args=[ TemplateArgument( arg=Type( typename=PQName( segments=[ FundamentalSpecifier( name="int" ) ] ) ) ) ] ), ), ], has_typename=True, ) ), ) ] ), ) ] ), parameters=[], template=TemplateDecl(), access="private", ) ], ), ] ) ) def test_template_instantiation() -> None: content = """ template class MyClass<1,2>; template class __attribute__(("something")) MyClass<3,4>; namespace foo { template class MyClass<5,6>; }; """ data = parse_string(content, cleandoc=True) assert data == ParsedData( namespace=NamespaceScope( template_insts=[ TemplateInst( typename=PQName( segments=[ NameSpecifier( name="MyClass", specialization=TemplateSpecialization( args=[ TemplateArgument( arg=Value(tokens=[Token(value="1")]) ), TemplateArgument( arg=Value(tokens=[Token(value="2")]) ), ] ), ) ] ), extern=False, ), TemplateInst( typename=PQName( segments=[ NameSpecifier( name="MyClass", specialization=TemplateSpecialization( args=[ TemplateArgument( arg=Value(tokens=[Token(value="3")]) ), TemplateArgument( arg=Value(tokens=[Token(value="4")]) ), ] ), ) ] ), extern=False, ), ], namespaces={ "foo": NamespaceScope( name="foo", template_insts=[ TemplateInst( typename=PQName( segments=[ NameSpecifier( name="MyClass", specialization=TemplateSpecialization( args=[ TemplateArgument( arg=Value(tokens=[Token(value="5")]) ), TemplateArgument( arg=Value(tokens=[Token(value="6")]) ), ] ), ) ] ), extern=False, ) ], ) }, ) ) def test_extern_template() -> None: content = """ extern template class MyClass<1,2>; extern template class __attribute__(("something")) MyClass<3,4>; namespace foo { extern template class MyClass<5,6>; }; """ data = parse_string(content, cleandoc=True) assert data == ParsedData( namespace=NamespaceScope( template_insts=[ TemplateInst( typename=PQName( segments=[ NameSpecifier( name="MyClass", specialization=TemplateSpecialization( args=[ TemplateArgument( arg=Value(tokens=[Token(value="1")]) ), TemplateArgument( arg=Value(tokens=[Token(value="2")]) ), ] ), ) ] ), extern=True, ), TemplateInst( typename=PQName( segments=[ NameSpecifier( name="MyClass", specialization=TemplateSpecialization( args=[ TemplateArgument( arg=Value(tokens=[Token(value="3")]) ), TemplateArgument( arg=Value(tokens=[Token(value="4")]) ), ] ), ) ] ), extern=True, ), ], namespaces={ "foo": NamespaceScope( name="foo", template_insts=[ TemplateInst( typename=PQName( segments=[ NameSpecifier( name="MyClass", specialization=TemplateSpecialization( args=[ TemplateArgument( arg=Value(tokens=[Token(value="5")]) ), TemplateArgument( arg=Value(tokens=[Token(value="6")]) ), ] ), ) ] ), extern=True, ) ], ) }, ) ) def test_fwd_declared_method() -> None: content = """ // forward declaration for specialized template function template <> Clazz::Clazz(); """ data = parse_string(content, cleandoc=True) assert data == ParsedData( namespace=NamespaceScope( method_impls=[ Method( return_type=None, name=PQName( segments=[ NameSpecifier( name="Clazz", specialization=TemplateSpecialization( args=[ TemplateArgument( arg=Type( typename=PQName( segments=[NameSpecifier(name="A")] ) ) ) ] ), ), NameSpecifier(name="Clazz"), ] ), parameters=[], template=TemplateDecl(), constructor=True, ) ] ) )