Difference between revisions of "C++0x: Variadic templates"

From Dwarf Wiki
Jump to: navigation, search
Line 22: Line 22:
 
array<double, 3, 3, 4, 5> t2;    // Dimensions is a template value parameter pack
 
array<double, 3, 3, 4, 5> t2;    // Dimensions is a template value parameter pack
 
                                   // containing three arguments: unsigned int 3, 4 and 5.
 
                                   // containing three arguments: unsigned int 3, 4 and 5.
 +
 +
template<typename... Args> 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.
 +
 
</pre>
 
</pre>
  
Line 56: Line 62:
 
|0x6A
 
|0x6A
 
|flag
 
|flag
|an argument within template parameters pack  
+
|an argument within function parameters pack  
 
|}
 
|}
  
Line 78: Line 84:
 
'''4.1: Data Object Entries'''
 
'''4.1: Data Object Entries'''
  
If a formal parameter is an argument within the template parameter pack, the formal parameter entry has a <tt>DW_AT_parameter_pack</tt> attribute, whose value is a flag.
+
If a formal parameter is an argument within the function parameter pack, the formal parameter entry has a <tt>DW_AT_parameter_pack</tt> attribute, whose value is a flag.  If a formal parameter is the first argument within the function parameter pack, the formal parameter entry has a <tt>DW_AT_name</tt> attribute, whose value is a null-terminated string containing the name of the function parameter pack.  All other formal parameters within the function parameter pack does not have a <tt>DW_AT_name</tt> attribute.
  
  
Line 84: Line 90:
  
 
<pre>
 
<pre>
void printf(const char* s) { }
+
/* Base case for printf */
 +
void printf(const char* s) {
 +
  while (*s) {
 +
    std::out << *s++;
 +
  }
 +
}
 
template<typename T, typename... Args>
 
template<typename T, typename... Args>
 
void printf(const char* s, T value, Args... args) {
 
void printf(const char* s, T value, Args... args) {
...
+
   while (*s) {
   printf (s, args...);
+
    if (*s == '%' && *++s != '%') {
... 
+
      std::cout << value;
 +
      return printf (++s, args...);
 +
    }
 +
    std::out << *s++;
 +
  }
 
}
 
}
  
Line 98: Line 113:
 
Compiler may instantiate these 4 functions as a result:
 
Compiler may instantiate these 4 functions as a result:
  
# printf<int,char,int> (const char* s, int, Args...);
+
# printf<int,char,int> (const char* s, int value, char, int); // args => char, int
# printf<char,int>    (const char* s, char, Args...);
+
# printf<char,int>    (const char* s, char value, int);       // args => int
# printf<int>          (const char* s, int, Args...);
+
# printf<int>          (const char* s, int value);             // args => (empty)
 
# printf              (const char* s);
 
# printf              (const char* s);
  
 
<pre>
 
<pre>
1) printf<int,char,int> (const char* s, int, Args...);
+
1) printf<int,char,int> (const char* s, int value, char, int); // args => char, int
 
<1><  ###>      DW_TAG_subprogram
 
<1><  ###>      DW_TAG_subprogram
 
                 DW_AT_name                  printf
 
                 DW_AT_name                  printf
Line 127: Line 142:
 
                 DW_AT_type                  <yyy>  // char
 
                 DW_AT_type                  <yyy>  // char
 
<2><  ###>      DW_TAG_formal_parameter
 
<2><  ###>      DW_TAG_formal_parameter
                DW_AT_name                  args
 
 
                 DW_AT_parameter_pack        yes
 
                 DW_AT_parameter_pack        yes
 
                 DW_AT_type                  <xxx>  // int
 
                 DW_AT_type                  <xxx>  // int
  
2) printf<char,int> (const char* s, char, Args...);
+
2) printf<char,int>     (const char* s, char value, int);       // args => int
 
<1><  ###>      DW_TAG_subprogram
 
<1><  ###>      DW_TAG_subprogram
 
                 DW_AT_name                  printf
 
                 DW_AT_name                  printf
Line 152: Line 166:
 
                 DW_AT_type                  <xxx>  // int
 
                 DW_AT_type                  <xxx>  // int
  
3) printf<int> (const char* s, int, Args...);
+
3) printf<int>         (const char* s, int value);             // args => (empty)
 
<1><  ###>      DW_TAG_subprogram
 
<1><  ###>      DW_TAG_subprogram
 
                 DW_AT_name                  printf
 
                 DW_AT_name                  printf
Line 174: Line 188:
 
                 DW_AT_type                  <zzz>  // const char*
 
                 DW_AT_type                  <zzz>  // const char*
 
</pre>
 
</pre>
 +
 +
 +
== Change History ==
 +
March 17, 2009.
 +
* Define template parameter pack and function parameter pack.
 +
* Add <tt>DW_AT_parameter_pack</tt> to indicate that a parameter is a part of template parameter pack.
 +
* Add naming convention for parameters which are part of template parameter pack.

Revision as of 06:32, 17 March 2009

For detail description of the feature, please refer to:

http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2006/n2087.pdf

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<typename... Elements> class tuple;
tuple<int, long> tuple_int_long;  // Elements is a template type parameter pack 
                                  // containing 2 arguments, int and long type
tuple<float> tuple_float;         // Elements is a template type parameter pack
                                     containing 1 argument: float type

template<typename T, unsigned PrimaryDimension, unsigned... Dimensions> class array;
array<double, 3, 3> t1;           // Dimensions is a template value parameter pack
                                  // containing a single argument: unsigned int 3.
array<double, 3, 3, 4, 5> t2;     // Dimensions is a template value parameter pack
                                  // containing three arguments: unsigned int 3, 4 and 5.

template<typename... Args> 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 change 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 tag

DW_TAG_template_parameter_pack 0x43 template parameters pack

Allowable attributes:

  • DECL
  • DW_AT_name
  • DW_AT_type
  • DW_AT_sibling


New DWARF attribute

DW_AT_parameter_pack 0x6A flag an argument within function parameters pack


3.3.7: Function Template Instantiations

Each template parameter pack declaration appearing in the template definition is represented by a debugging information entry with the tag DW_TAG_template_parameter_pack. Each such entry may have a DW_AT_name attribute, whose value is a null-terminated string containing the name of the template parameter pack as it appears in the source program.

Template parameter pack entries can have zero or more child entries. Each entry correspond to exactly one argument within the template parameter pack. This child entry must have the tag DW_TAG_template_type_parameter, and will have same form as other template type parameter entries.


5.6.8: Class Template Instantiations

Each template parameter pack declaration appearing in the template definition is represented by a debugging information entry with the tag DW_TAG_template_parameter_pack. Each such entry may have a DW_AT_name attribute, whose value is a null-terminated string containing the name of the template parameter pack as it appears in the source program.

If the template parameter pack entry represent a template value parameter pack, it may contain a DW_AT_type attribute to denote the type of the arguments within the template value parameter pack.

Template parameter pack entries can have zero or more child entries. Each entry correspond to exactly one argument within the template parameter pack. This child entry can have one of the tags DW_TAG_template_type_parameter or DW_TAG_template_value_parameter, and will have same form as other template parameter entries.


4.1: Data Object Entries

If a formal parameter is an argument within the function parameter pack, the formal parameter entry has a DW_AT_parameter_pack attribute, whose value is a flag. If a formal parameter is the first argument within the function parameter pack, the formal parameter entry has a DW_AT_name attribute, whose value is a null-terminated string containing the name of the function parameter pack. All other formal parameters within the function parameter pack does not have a DW_AT_name attribute.


Example

/* Base case for printf */
void printf(const char* s) {
  while (*s) {
    std::out << *s++;
  }
}
template<typename T, typename... Args>
void printf(const char* s, T value, Args... args) {
  while (*s) {
    if (*s == '%' && *++s != '%') {
      std::cout << value;
      return printf (++s, args...);
    }
    std::out << *s++;
  }
}

int x;
printf<int, char, int> ("%c %d", x, 'x', 3);

Compiler may instantiate these 4 functions as a result:

  1. printf<int,char,int> (const char* s, int value, char, int); // args => char, int
  2. printf<char,int> (const char* s, char value, int); // args => int
  3. printf<int> (const char* s, int value); // args => (empty)
  4. printf (const char* s);
1) printf<int,char,int> (const char* s, int value, char, int);  // args => char, int
<1><  ###>      DW_TAG_subprogram
                DW_AT_name                  printf
<2><  ###>      DW_TAG_template_type_parameter
                DW_AT_name                  T
                DW_AT_type                  <xxx>  // int
<2><  ###>      DW_TAG_template_parameter_pack
                DW_AT_name                  Args
<3><  ###>      DW_TAG_template_type_parameter
                DW_AT_type                  <yyy>  // char
<3><  ###>      DW_TAG_template_type_parameter
                DW_AT_type                  <xxx>  // int
<2><  ###>      DW_TAG_formal_parameter
                DW_AT_name                  s
                DW_AT_type                  <zzz>  // const char*
<2><  ###>      DW_TAG_formal_parameter
                DW_AT_name                  value
                DW_AT_type                  <xxx>  // int
<2><  ###>      DW_TAG_formal_parameter
                DW_AT_name                  args
                DW_AT_parameter_pack        yes
                DW_AT_type                  <yyy>  // char
<2><  ###>      DW_TAG_formal_parameter
                DW_AT_parameter_pack        yes
                DW_AT_type                  <xxx>  // int

2) printf<char,int>     (const char* s, char value, int);       // args => int
<1><  ###>      DW_TAG_subprogram
                DW_AT_name                  printf
<2><  ###>      DW_TAG_template_type_parameter
                DW_AT_name                  T
                DW_AT_type                  <yyy>  // char
<2><  ###>      DW_TAG_template_parameter_pack
                DW_AT_name                  Args
<3><  ###>      DW_TAG_template_type_parameter
                DW_AT_type                  <xxx>  // int
<2><  ###>      DW_TAG_formal_parameter
                DW_AT_name                  s
                DW_AT_type                  <zzz>  // const char*
<2><  ###>      DW_TAG_formal_parameter
                DW_AT_name                  value
                DW_AT_type                  <yyy>  // char
<2><  ###>      DW_TAG_formal_parameter
                DW_AT_name                  args
                DW_AT_parameter_pack        yes
                DW_AT_type                  <xxx>  // int

3) printf<int>          (const char* s, int value);             // args => (empty)
<1><  ###>      DW_TAG_subprogram
                DW_AT_name                  printf
<2><  ###>      DW_TAG_template_type_parameter
                DW_AT_name                  T
                DW_AT_type                  <xxx>  // int
<2><  ###>      DW_TAG_template_parameter_pack
                DW_AT_name                  Args
<2><  ###>      DW_TAG_formal_parameter
                DW_AT_name                  s
                DW_AT_type                  <zzz>  // const char*
<2><  ###>      DW_TAG_formal_parameter
                DW_AT_name                  value
                DW_AT_type                  <xxx>  // int

4) printf (const char* s);
<1><  ###>      DW_TAG_subprogram
                DW_AT_name                  printf
<2><  ###>      DW_TAG_formal_parameter
                DW_AT_name                  s
                DW_AT_type                  <zzz>  // const char*


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.