// @trick_parse{everything} #ifndef Classes_HH #define Classes_HH template class Foo {}; namespace peer { template class Bar {}; struct Leek { template class Eggplant {}; }; namespace nested { template class Broccoli {}; struct Carrot { template class Celery {}; }; } } namespace prime { template class Potato {}; struct Turnip { template class Radish {}; }; namespace nested { template class Baz {}; struct Artichoke { template class Asparagus {}; }; } struct Onion { // ======================= WORKING ============================================= /** * We assume a qualified template instantiation is fully qualified * starting from the global namespace, and we put the corresponding * %template directive in the global namespace, which works if our * assumption is correct. */ ::Foo fooInt; peer::Bar barInt; ::peer::Bar barDouble; peer::Leek::Eggplant eggplantInt; ::peer::Leek::Eggplant eggplantDouble; peer::nested::Broccoli broccoliInt; ::peer::nested::Broccoli broccoliDouble; peer::nested::Carrot::Celery celeryInt; ::peer::nested::Carrot::Celery celeryDouble; prime::Potato potatoInt; ::prime::Potato potatoDouble; prime::Turnip::Radish radishInt; ::prime::Turnip::Radish radishDouble; prime::nested::Baz bazInt; ::prime::nested::Baz bazDouble; prime::nested::Artichoke::Asparagus asparagusint; ::prime::nested::Artichoke::Asparagus asparagusDouble; /** * We put the %template directive for unqualified template * instantiations in the namespace containing the current class, * which only works if the template is defined in that namespace as * well. */ Potato potatoBool; // ======================= BROKEN ============================================== /** * Because Foo is declared in the global namespace, its %template * directive must be in that scope as well. However, because the * template instation here is unqualified, we put the %template * directive in the containing namespace, which is an error. * * Error: 'Foo' resolves to '::Foo' and was incorrectly * instantiated in scope 'prime' instead of within scope ''. */ // Foo fooDouble; /** * Because these template instantiations are qualified, their %template * directives are placed in the global namespace. However, because they * are not _fully_ qualified, the generated SWIG input code is invalid. * For partially-qualified instantiations, the directive should either be: * 1. Declared in the global namespace and qualified with prime:: * 2. Declared in the prime namespace * * We don't track enough information to do either. * * Error: Template 'Turnip::Radish' undefined. * Error: Template 'nested::Baz' undefined. * Error: Template 'nested::Artichoke::Asparagus' undefined. */ // Turnip::Radish radishBool; // nested::Baz bazBool; // nested::Artichoke::Asparagus asparagusBool; template class InnerOnion {}; // onions have layers! /** * All %template directives are placed before the class containing their * corresponding template instantiations. For member templates * (templates declared within the class being processed), this results * in the %template directive referencing the member template before it * has been declared, which is an error. * * Error: Template 'InnerOnion' undefined. * Error: Template 'Onion::InnerOnion' undefined. * Error: Template 'prime::Onion::InnerOnion' undefined. * Error: Template '::prime::Onion::InnerOnion' undefined. */ // InnerOnion layer1; // Onion::InnerOnion layer2; // prime::Onion::InnerOnion layer2; // ::prime::Onion::InnerOnion layer4; }; // Same tests as above, but within a nested namespace. namespace nested { class Corn { ::Foo fooLeek; peer::Bar > barFoo; ::peer::Bar barLeek; peer::Leek::Eggplant eggplantLong; ::peer::Leek::Eggplant eggplantLeek; peer::nested::Broccoli broccoliLong; ::peer::nested::Broccoli broccoliLeek; peer::nested::Carrot::Celery celeryLong; ::peer::nested::Carrot::Celery celeryLeek; prime::Potato potatoLong; ::prime::Potato potatoLeek; prime::Turnip::Radish radishLong; ::prime::Turnip::Radish radishLeek; prime::nested::Baz bazLong; ::prime::nested::Baz bazLeek; prime::nested::Artichoke::Asparagus asparagusLong; ::prime::nested::Artichoke::Asparagus asparagusLeek; // These fail in Onion, but work here because Onion has already been processed. prime::Onion::InnerOnion onionLong; ::prime::Onion::InnerOnion onionLeek; // These fail for the same reason as in Onion. // Foo fooFloat; // Turnip::Radish radishFloat; // nested::Baz bazFloat; // nested::Artichoke::Asparagus asparagusFloat; // Onion::InnerOnion innerOnionFloat; }; } } #endif