首先尝试类型参数。
7654 static tree
7655 cp_parser_template_parameter (cp_parser* parser) in parser.c
7656 {
7657 cp_token *token;
7658
7659 /* Peek at the next token. */
7660 token = cp_lexer_peek_token (parser->lexer);
…
7677 if (token->keyword == RID_TYPENAME || token->keyword == RID_CLASS)
7678 {
7679 /* Peek at the token after `class' or `typename'. */
7680 token = cp_lexer_peek_nth_token (parser->lexer, 2);
7681 /* If it's an identifier, skip it. */
7682 if (token->type == CPP_NAME)
7683 token = cp_lexer_peek_nth_token (parser->lexer, 3);
7684 /* Now, see if the token looks like the end of a template
7685 parameter. */
7686 if (token->type == CPP_COMMA
7687 || token->type == CPP_EQ
7688 || token->type == CPP_GREATER)
7689 return cp_parser_type_parameter (parser);
7690 }
…
7703 }
当看到 “ <class Host> ”, 因为 “ Host ” 后面只跟着 “ > ”, 解析器明白这是个类型参数 , 在上面的 7689 行 , 进入 cp_parser_type_parameter 。
7720 static tree
7721 cp_parser_type_parameter (cp_parser* parser) in parser.c
7722 {
7723 cp_token *token;
7724 tree parameter;
7725
7726 /* Look for a keyword to tell us what kind of parameter this is. */
7727 token = cp_parser_require (parser, CPP_KEYWORD,
7728 "`class', `typename', or `template'");
7729 if (!token)
7730 return error_mark_node;
7731
7732 switch (token->keyword)
7733 {
7734 case RID_CLASS:
7735 case RID_TYPENAME:
7736 {
7737 tree identifier;
7738 tree default_argument;
7739
7740 /* If the next token is an identifier, then it names the
7741 parameter. */
7742 if (cp_lexer_next_token_is (parser->lexer, CPP_NAME))
7743 identifier = cp_parser_identifier (parser);
7744 else
7745 identifier = NULL_TREE;
7746
7747 /* Create the parameter. */
7748 parameter = finish_template_type_parm (class_type_node , identifier);
7749
7750 /* If the next token is an `=', we have a default argument. */
7751 if (cp_lexer_next_token_is (parser->lexer, CPP_EQ))
7752 {
7753 /* Consume the `=' token. */
7754 cp_lexer_consume_token (parser->lexer);
7755 /* Parse the default-argument. */
7756 default_argument = cp_parser_type_id (parser);
7757 }
7758 else
7759 default_argument = NULL_TREE;
7760
7761 /* Create the combined representation of the parameter and the
7762 default argument. */
7763 parameter = build_tree_list (default_argument, parameter);
7764 }
7765 break ;
7766
7767 case RID_TEMPLATE:
7768 {
...
7842 }
7843 break ;
7844
7845 default:
7846 abort ();
7847 break ;
7848 }
7849
7850 return parameter;
7851 }
因为认出了用于模板参数的标识符 ,一个树节点需要为之创建,这是一个 tree_list 类型节点。
1928 tree
1929 finish_template_type_parm (tree aggr, tree identifier) in sematics.c
1930 {
1931 if (aggr != class_type_node )
1932 {
1933 pedwarn ("template type parameters must use the keyword `class' or `typename'");
1934 aggr = class_type_node ;
1935 }
1936
1937 return build_tree_list (aggr, identifier);
1938 }
所产生的模板参数看起来如下图(它没有默认参数)。
图 48 :模板参数“ Host ”的布局