# Support C++0x Variadic templates This proposal was originally submitted as [090107.2][090107.2]. [090107.2]: https://dwarfstd.org/issues/090107.2.html In the DWARF commmittee meeting on June 2, 2009, four options were presented: 1. `DW_TAG_template_parameter_pack`/`DW_TAG_formal_parameter_pack` is used as marker. 2. Make `DW_TAG_template_type_parameter` DIEs children of `DW_TAG_template_parameter_pack`. And make `DW_TAG_formal_parameter` DIEs children of `DW_TAG_formal_parameter_pack`. 3. Create new children DIEs under `DW_TAG_template_parameter_pack`/`DW_TAG_formal_parameter_pack` DIE and add references to `DW_TAG_template_type_parameter`/`DW_TAG_formal_parameter` respectively. 4. Reject Variadic templates proposal. The consensus was to reject the proposal and wait for a vendor to produce the information first. ## Background For a detailed description of the feature, please refer to: - [A Brief Introduction to Variadic Templates][n2087] - [Variadic Templates (Revision 3)][n2080] [n2087]: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2006/n2087.pdf [n2080]: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2006/n2080.pdf ## Overview C++0x will allow function and class templates to take an arbitrary number of arguments. The motivation behind this language extension is to allow TR1 facilities such as tuple to accept variable number of parameters. template class tuple; tuple tuple_int_long; // Elements is a template type parameter pack // containing 2 arguments, int and long type tuple tuple_float; // Elements is a template type parameter pack containing 1 argument: float type template class array; array t1; // Dimensions is a template value parameter pack // containing a single argument: unsigned int 3. array t2; // Dimensions is a template value parameter pack // containing three arguments: unsigned int 3, 4 and 5. template void eat(Args... args); // The eat() function is a variadic template with template parameter pack Args. // The ellipsis to the left of the identifier args indicates that args is a // function parameter pack. ## Proposed changes to DWARF ### Purpose - DWARF does not represent the generic template definition, but does represent each template instantiation. - Template type parameter pack contains only template type parameters - Template value parameter pack contains only template value parameters - Debug information should show where the template parameter pack is used within the template definition. - If possible, debug information should also show the arguments within the template parameter pack. ### New DWARF tags Add the following new tags to Table 2.1, "Tag names", to Table 7.3, "Tag encodings", and to Table A.1, "Attributes by tag value": - `DW_TAG_template_parameter_pack` Allowable attributes: - DECL - `DW_AT_name` - `DW_AT_sibling` - `DW_TAG_formal_parameter_pack` Allowable attributes: - DECL - `DW_AT_name` - `DW_AT_sibling` ### 2.23: Template Parameters Replace the third and fourth paragraphs with the following: > A template type parameter is represented by a debugging information entry with > the tag `DW_TAG_template_type_parameter`. A template value parameter is > represented by a debugging information entry with the tag > `DW_TAG_template_value_parameter`. A template parameter pack is represented by a > debugging information entry with the tag `DW_TAG_template_parameter_pack`. The > actual template parameter entries appear in the same order as the corresponding > template formal parameter declarations in the source program. > > Each element of a parameter pack is represented by a debugging information > entry for a type or value parameter. These entries are children of the > debugging information entry with the tag `DW_TAG_template_parameter_pack`. > Each such entry does not have a `DW_AT_name` attribute. > > Except as above, a type or value parameter or parameter > pack entry may have a `DW_AT_name` attribute, whose value is a > null-terminated string containing the name of the corresponding formal > parameter. The A type or value parameter entry > may also have a `DW_AT_default_value` attribute, which is a > flag indicating that the value corresponds to the default argument for the > template parameter. ### 3.3.7: Function Template Instantiations Add the following numbered item following item #1 (renumbering items 2 and 3): > 2\. Each function parameter pack declaration appearing in the template > definition is represented by a debugging information entry with the tag > `DW_TAG_formal_parameter_pack`. Each such entry may have a `DW_AT_name` > attribute, whose value is a null-terminated string containing the name > of the function parameter pack as it appears in the source program. > > Each element of the function parameter pack is represented by a > debugging information entry with the tag `DW_TAG_formal_parameter`. > These entries are children of the debugging information entry with the > tag `DW_TAG_formal_parameter_pack`. Each such entry does not have a > `DW_AT_name` attribute. Each such entry has a `DW_AT_type` attribute > describing the type of the formal parameter in this instantiation. ## APPENDIX D: Examples ### D.8 Variadic Templates Examples #### D.8.1 Function Template Instantiations /* Base case for printf */ void printf(const char* s) { while (*s) { std::cout << *s++; } } template void printf(const char* s, T value, PackTypes... args) { while (*s) { if (*s == '%' && *++s != '%') { std::cout << value; return printf (++s, args...); } std::cout << *s++; } } int x; printf ("%c %d", x, 'x', 3); The base case for printf is not a template instantiation: printf (const char* s); 1$: DW_TAG_subprogram DW_AT_name("printf") 2$: DW_TAG_formal_parameter DW_AT_name("s") DW_AT_type(reference to type "const char*") Compiler may instantiate these 3 functions: # printf (const char* s, int value, char, int); // args => char, int # printf (const char* s, char value, int); // args => int # printf (const char* s, int value); // args => (empty) 1) printf (const char* s, int value, char, int); // args => char, int 10$: DW_TAG_subprogram DW_AT_name("printf") 11$: DW_TAG_template_type_parameter DW_AT_name("T") DW_AT_type(reference to base type "int") 12$: DW_TAG_template_parameter_pack DW_AT_name("PackTypes") 13$: DW_TAG_template_type_parameter ! no DW_AT_name attribute DW_AT_type(reference to base type "char") 14$: DW_TAG_template_type_parameter ! no DW_AT_name attribute DW_AT_type(reference to base type "int") 15$: DW_TAG_formal_parameter DW_AT_name("s") DW_AT_type(reference to type "const char*") 16$: DW_TAG_formal_parameter DW_AT_name("value") DW_AT_type(reference to base type "int") 17$: DW_TAG_formal_parameter_pack DW_AT_name("args") 18$: DW_TAG_formal_parameter ! no DW_AT_name attribute DW_AT_type(reference to base type "char") 19$: DW_TAG_formal_parameter ! no DW_AT_name attribute DW_AT_type(reference to base type "int") 2) printf (const char* s, char value, int); // args => int 20$: DW_TAG_subprogram DW_AT_name("printf") 21$: DW_TAG_template_type_parameter DW_AT_name("T") DW_AT_type(reference to base type "int") 22$: DW_TAG_template_parameter_pack DW_AT_name("PackTypes") 23$: DW_TAG_template_type_parameter ! no DW_AT_name attribute DW_AT_type(reference to base type "int") 24$: DW_TAG_formal_parameter DW_AT_name("s") DW_AT_type(reference to type "const char*") 25$: DW_TAG_formal_parameter DW_AT_name("value") DW_AT_type(reference to base type "char") 26$: DW_TAG_formal_parameter_pack DW_AT_name("args") 27$: DW_TAG_formal_parameter ! no DW_AT_name attribute DW_AT_type(reference to base type "int") 3) printf (const char* s, int value); // args => (empty) 30$: DW_TAG_subprogram DW_AT_name("printf") 31$: DW_TAG_template_type_parameter DW_AT_name("T") DW_AT_type(reference to base type "int") 32$: DW_TAG_template_parameter_pack DW_AT_name("PackTypes") 33$: DW_TAG_formal_parameter DW_AT_name("s") DW_AT_type(reference to type "const char*") 34$: DW_TAG_formal_parameter DW_AT_name("value") DW_AT_type(reference to base type "int") 35$: DW_TAG_formal_parameter_pack DW_AT_name("args") #### D.8.2 Class Template Instantiations /* Template definition for counting number of template type arguments */ template struct count; /* Full specialization for zero argument */ template <> struct count<> { static const int value = 0; }; /* Partial specialization for peeling off the first argument */ template struct count { static const int value = 1 + count::value; }; /* Template instantiation */ count a; The base case template: 1$: DW_TAG_structure_type DW_AT_name("count") 2$: DW_TAG_member DW_AT_name("value") DW_AT_declaration(yes) DW_AT_type(reference to type "const int") 3$: DW_TAG_variable DW_AT_specification(reference to 2$) DW_AT_location(...) Compiler may instantiate these 3 types: 1) count // PackTypes => short, int 11$: DW_TAG_structure_type DW_AT_name("count") 12$: DW_TAG_template_type_parameter DW_AT_name("T") DW_AT_type(reference to base type "char") 13$: DW_TAG_template_parameter_pack DW_AT_name("PackTypes") 14$: DW_TAG_template_type_parameter DW_AT_type(reference to base type "short") 15$: DW_TAG_template_type_parameter DW_AT_type(reference to base type "int") 16$: DW_TAG_member DW_AT_name("value") DW_AT_declaration(yes) DW_AT_type(reference to type "const int") 17$: DW_TAG_variable DW_AT_specification(reference to 16$) DW_AT_location(...) 2) count // PackTypes => int 21$: DW_TAG_structure_type DW_AT_name("count") 22$: DW_TAG_template_type_parameter DW_AT_name("T") DW_AT_type(reference to base type "short") 23$: DW_TAG_template_parameter_pack DW_AT_name("PackTypes") 24$: DW_TAG_template_type_parameter DW_AT_type(reference to base type "int") 25$: DW_TAG_member DW_AT_name("value") DW_AT_declaration(yes) DW_AT_type(reference to type "const int") 26$: DW_TAG_variable DW_AT_specification(reference to 25$) DW_AT_location(...) 3) count // PackTypes => (empty) 31$: DW_TAG_structure_type DW_AT_name("count") 32$: DW_TAG_template_type_parameter DW_AT_name("T") DW_AT_type(reference to base type "int") 33$: DW_TAG_template_parameter_pack DW_AT_name("PackTypes") 34$: DW_TAG_member DW_AT_name("value") DW_AT_declaration(yes) DW_AT_type(reference to type "const int") 35$: DW_TAG_variable DW_AT_specification(reference to 34$) DW_AT_location(...) 4) count a; 41$: DW_TAG_variable DW_AT_name("a") DW_AT_type(reference to 11$) DW_AT_location(...) #### D.8.3 Multiple template packs in template definition template struct pair { void showself () { std::cout << I << std::endl; X local; local.showself(); } }; struct a1 { void showself () { std::cout << "a1" << std::endl; }}; struct a2 { void showself () { std::cout << "a2" << std::endl; }}; template void showself (pair headArg, pair... restArg) { headArg.showself(); showself (restArg...); } /* Instantiations */ pair t1; pair t2; showself(t1,t2); First the simple structures: struct a1 { void showself () { std::cout << "a1" << std::endl; }}; 11$: DW_TAG_structure_type DW_AT_name("a1") 12$: DW_TAG_subprogram DW_AT_name("showself") DW_AT_type(reference to type "void") struct a2 { void showself () { std::cout << "a2" << std::endl; }}; 21$: DW_TAG_structure_type DW_AT_name("a2") 22$: DW_TAG_subprogram DW_AT_name("showself") DW_AT_type(reference to type "void") DWARF for 'pair' structures: pair t1; 31$: DW_TAG_structure_type DW_AT_name("pair") 32$: DW_TAG_template_type_parameter DW_AT_name("X") DW_AT_type(reference to 11$) 33$: DW_TAG_template_value_parameter DW_AT_name("I") DW_AT_type(reference to base type "int") DW_AT_const_value(1) 33$: DW_TAG_subprogram DW_AT_name("showself") DW_AT_type(reference to type "void") 34$: DW_TAG_variable DW_AT_name("t1") DW_AT_type(reference to 31$) DW_AT_location(...) pair t2; 41$: DW_TAG_structure_type DW_AT_name("pair") 42$: DW_TAG_template_type_parameter DW_AT_name("X") DW_AT_type(reference to 21$) 43$: DW_TAG_template_value_parameter DW_AT_name("I") DW_AT_type(reference to base type "int") DW_AT_const_value(2) 43$: DW_TAG_subprogram DW_AT_name("showself") DW_AT_type(reference to type "void") 44$: DW_TAG_variable DW_AT_name("t2") DW_AT_type(reference to 41$) DW_AT_location(...) The variadic template function showself(): template void showself (pair headArg, pair... restArg) { headArg.showself(); showself (restArg...); } showself (pair, pair): 51$: DW_TAG_subprogram DW_AT_name("showself") 52$: DW_TAG_template_type_parameter DW_AT_name("headX") DW_AT_type(reference to 11$) 53$: DW_TAG_template_value_parameter DW_AT_name("headI") DW_AT_type(reference to base type "int") DW_AT_const_value(1) 54$: DW_TAG_template_parameter_pack DW_AT_name("restX") 55$: DW_TAG_template_type_parameter DW_AT_type(reference to 21$) 56$: DW_TAG_template_parameter_pack DW_AT_name("restI") DW_AT_type(reference to base type "int") 57$: DW_TAG_template_value_parameter DW_AT_const_value(2) 58$: DW_TAG_formal_parameter DW_AT_name("headArg") DW_AT_type(reference to 31$) 59$: DW_TAG_formal_parameter_pack DW_AT_name("restArg") 60$: DW_TAG_formal_parameter ! no DW_AT_name attribute DW_AT_type(reference to 41$) showself (pair): 71$: DW_TAG_subprogram DW_AT_name("showself") 72$: DW_TAG_template_type_parameter DW_AT_name("headX") DW_AT_type(reference to 21$) 73$: DW_TAG_template_value_parameter DW_AT_name("headI") DW_AT_type(reference to base type "int") DW_AT_const_value(2) 74$: DW_TAG_template_parameter_pack DW_AT_name("restX") 75$: DW_TAG_template_parameter_pack DW_AT_name("restI") 76$: DW_TAG_formal_parameter DW_AT_name("headArg") DW_AT_type(reference to 41$) 77$: DW_TAG_formal_parameter_pack DW_AT_name("restArg") ## Change History March 17, 2009. - Define template parameter pack and function parameter pack. - Add `DW_AT_parameter_pack` to indicate that a parameter is a part of template parameter pack. - Add naming convention for parameters which are part of template parameter pack. April 13, 2009. - Place Example section in Appendix D - Re-format DWARF description in Example section to match current documentation. - Remove `DW_AT_parameter_pack` attribute - Add example of class template instantiation with template parameter pack. May 5, 2009. - Add `DW_TAG_formal_parameter_pack` to indicate the name of the function parameter pack. - `DW_TAG_template_type_parameter` are not longer children of `DW_TAG_template_parameter_pack`. This is made so that consumer don't need to understand the new TAG, and still be able to process the other information. - Add debug information representation for variable 'a' in D.8.2. June 2, 2009. - Add example for multiple template parameter pack in template definition. September 11, 2009. - Dodji Seketeli points out that function parameter packs do not have to be located at the end of a parameter-declaration-list [[n2939#US45][us45]] This provides the argument that `DW_TAG_formal_parameter_pack` can not be used as marker. And for consistency, `DW_TAG_template_parameter_pack` can follow the same behavior as `DW_TAG_formal_parameter_pack`. - Adjust examples to make `DW_TAG_template_type_parameter` and `DW_TAG_formal_parameter` children of `DW_TAG_template_parameter_pack` and `DW_TAG_formal_parameter_pack` respectively. July 6, 2025. - Correct formal parameter types in examples to match the specification. - Refactor to change 2.23 and not 5.6.8. [us45]: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2009/n2939.html#US45 --- 2025-08-04: Accepted, with possible editorial changes. 2025-09-15: [Editorial changes][diff1]. List tables needing change due to new DWARF tags; Clarify scope of changes to Sections 2.23 and 3.3.7; Clarified text to disallow `DW_AT_default_value` attribute on parameter pack entries. In Section 3.3.7, combined items 4 and 5 and inserted between old items 1 and 2. Of the examples given, only the printf example will be added to Appendix D.