5.13.1.1.2.1.2.
添加模板方法
下面的隐式转换的机制将尝试查是否能隐式地调用某个模板转换操作符。这个过程不能被命令行选项“
–fimiplicit-template
”所关闭。因为该模板函数是隐式调用的,它不能直接地指定模板实参;该模板实参只能根据调用实参推导。而那些不能推导出来的,将不被选中。
在调用点上,
ctype
是‘
this
’指针的类型,
explicit_targs
是显式模板实参;
arglist
是提供的实参;而
return_type
则是对于转换操作符而言理想的类型(或者对于普通的模板函数,它是
NULL
)。然后
access_path
是访问该函数的类(这里是‘
this
’指针的类型),而
conversion_path
则是定义该函数的类的
binfo
。
2134
static
struct
z_candidate *
2135
add_template_candidate
(struct
z_candidate
**candidates, tree tmpl, tree ctype,
in
call.c
2136
tree
explicit_targs, tree arglist, tree return_type,
2137
tree
access_path, tree conversion_path, int flags,
2138
unification_kind_t strict)
2139
{
2140
return
2141
add_template_candidate_real
(candidates, tmpl, ctype,
2142
explicit_targs,
arglist, return_type,
2143
access_path,
conversion_path,
2144
flags, NULL_TREE,
strict);
2145
}
另外,在这里
strict
对于普通模板函数是
DEDUCE_CALL
(或者对于转换操作符,则是
DEDUCE_CONV
);并且在下面
add_template_candidate_real
的调用中,把
NULL
传给
obj
。
2035
static
struct
z_candidate*
2036
add_template_candidate_real
(struct
z_candidate
**candidates, tree tmpl,
in call.c
2037
tree
ctype, tree explicit_targs, tree arglist,
2038
tree
return_type, tree access_path,
2039
tree
conversion_path, int flags, tree obj,
2040
unification_kind_t
strict)
2041
{
2042
int ntparms = DECL_NTPARMS
(tmpl);
2043
tree targs = make_tree_vec
(ntparms);
2044
tree args_without_in_chrg =
arglist;
2045
struct
z_candidate *cand;
2046
int i;
2047
tree fn;
2048
2049
/*
We don't do deduction on the in-charge parameter, the VTT
2050
parameter or 'this'.
*/
2051
if
(DECL_NONSTATIC_MEMBER_FUNCTION_P (tmpl))
2052
args_without_in_chrg =
TREE_CHAIN (args_without_in_chrg);
2053
2054
if
((DECL_MAYBE_IN_CHARGE_CONSTRUCTOR_P (tmpl)
2055
|| DECL_BASE_CONSTRUCTOR_P
(tmpl))
2056
&&
TYPE_USES_VIRTUAL_BASECLASSES (DECL_CONTEXT (tmpl)))
2057
args_without_in_chrg =
TREE_CHAIN (args_without_in_chrg);
2058
2059
i = fn_type_unification
(tmpl, explicit_targs,
targs,
2060
args_without_in_chrg,
2061
return_type, strict, -1);
在上面,
DECL_NTPARMS
返回
tmpl
的模板形参的个数;相应地,
targs
是保存推导出的实参的
vector
;而
args_without_in_chrg
,由其名字所示,将保存除了那些主管参数(
in-charge
parameter
,即‘
this
’指针,
VTT
等)以外的实参。
5.12.4.1.1.2.2.1.
模板实参推导
下面给出了【
3
】的条文
clause 14.8.2
“模板实参推导”
[temp.deduct
]
。
1. void f(Array<dcomplex>& cv, Array<int>& ci) { sort(cv); // call sort(ci); // call } 及 void g(double d) { int i = convert<int>(d); int c = convert<char>(d); } —例子结束 2. — — — Ø template int I = f<int>(0); int j = f<void>(0); Ø template int i = f<int>(0); ] Ø template struct struct int i = f<A>(0); int j = f<C>(0); ] Ø Ø Ø template int i = f<int>(0); ] Ø template int i2 = f<int,1>(0); Ø Ø 3. template template template int main() { f<int>(1); f<const g<int>(1); g<const h<const } —例子结束 4. 5. template template int i1 = f<1>(0); int i2 = f<1000>(0); —例子结束 |
如果模板实参推导成功,下面的函数返回
0
。
8893
int
8894
fn_type_unification
(tree fn,
in
pt.c
8895
tree
explicit_targs,
8896
tree targs,
8897
tree args,
8898
tree
return_type,
8899
unification_kind_t
strict,
8900
int len)
8901
{
8902
tree parms;
8903
tree fntype;
8904
int result;
8905
8906
my_friendly_assert
(TREE_CODE (fn) == TEMPLATE_DECL, 0);
8907
8908
fntype = TREE_TYPE (fn);
8909
if (explicit_targs)
8910
{
8911
/*
[temp.deduct]
8912
8913
The
specified template arguments must match the template
8914
parameters in kind (i.e., type, nontype,
template), and there
8915
must
not be more arguments than there are parameters;
8916
otherwise type deduction fails.
8917
8918
Nontype arguments must match the types of
the corresponding
8919
nontype template parameters, or must be
convertible to the
8920
types of the corresponding nontype
parameters as specified in
8921
_temp.arg.nontype_, otherwise type
deduction fails.
8922
8923
All
references in the function type of the function template
8924
to
the corresponding template parameters are replaced by the
8925
specified template argument values. If a
substitution in a
8926
template parameter or in the function
type of the function
8927
template results in an invalid type, type
deduction fails.
*/
8928
int i;
8929
tree converted_args;
8930
bool incomplete;
8931
8932
if (explicit_targs ==
error_mark_node)
8933
return
1;
8934
8935
converted_args
8936
= (coerce_template_parms
(DECL_INNERMOST_TEMPLATE_PARMS
(fn),
8937
explicit_targs,
NULL_TREE, tf_none,
8938
/*require_all_arguments=*/
0));
8939
if (converted_args ==
error_mark_node)
8940
return
1;
8941
8942
/*
Substitute the explicit args into the function type. This is
8943
necessary so that, for instance,
explicitly declared function
8944
arguments can match null pointed
constants. If we were given
8945
an
incomplete set of explicit args, we must not do semantic
8946
processing during substitution as we could
create partial
8947
instantiations.
*/
8948
incomplete = NUM_TMPL_ARGS
(explicit_targs) != NUM_TMPL_ARGS (targs);
8949
processing_template_decl
+=
incomplete;
8950
fntype = tsubst (fntype,
converted_args, tf_none, NULL_TREE);
8951
processing_template_decl
-=
incomplete;
8952
8953
if (fntype ==
error_mark_node)
8954
return
1;
8955
8956
/*
Place the explicitly specified arguments in TARGS.
*/
8957
for
(i = NUM_TMPL_ARGS (converted_args); i--;)
8958
TREE_VEC_ELT (targs, i)
= TREE_VEC_ELT (converted_args, i);
8959
}
参数
explicit_args
是显式模板实参,例如,通过一个
template-id
来提供。我们已经在前一节看过了
coerce_template_parms
的一个例子,它转换显式模板实参来匹配形参,而其结果返回给
8935
行的
converted_arg
。那么在
8950
行的
tsubst
用转换后的实参替代模板形参。
fn_type_unification (continue)
8961
parms = TYPE_ARG_TYPES
(fntype);
8962
/*
Never do unification on the 'this' parameter.
*/
8963
if
(DECL_NONSTATIC_MEMBER_FUNCTION_P (fn))
8964
parms = TREE_CHAIN
(parms);
8965
8966
if (return_type)
8967
{
8968
/*
We've been given a return type to match, prepend it.
*/
8969
parms = tree_cons
(NULL_TREE, TREE_TYPE (fntype), parms);
8970
args = tree_cons
(NULL_TREE, return_type, args);
8971
if (len >= 0)
8972
++len;
8973
}
8974
8975
/* We allow incomplete unification without an
error message here
8976
because the standard doesn't seem to
explicitly prohibit it. Our
8977
callers must be ready to deal with
unification failures in any
8978
event.
*/
8979
result = type_unification_real
(DECL_INNERMOST_TEMPLATE_PARMS
(fn),
8980
targs, parms, args, /*subr=*/
0,
8981
strict,
/*allow_incomplete*/
1, len);
8982
8983
if (result == 0)
8984
/*
All is well so far. Now, check:
8985
8986
[temp.deduct]
8987
8988
When
all template arguments have been deduced, all uses of
8989
template parameters in nondeduced
contexts are replaced with
8990
the
corresponding deduced argument values. If the
8991
substitution results in an invalid type,
as described above,
8992
type
deduction fails.
*/
8993
if (tsubst (TREE_TYPE
(fn), targs, tf_none, NULL_TREE)
8994
==
error_mark_node)
8995
return
1;
8996
8997
return
result;
8998
}
记住现在正在处理函数模板。
在下面的函数中,
tparms
指向模板形参;
targs
是保存将在这里得到的推导后的模板实参的
vector
(它可能是空的,如果给出了显式模板实参。它包含转换后的这些实参);
xparms
是该转换操作符包含返回类型的参数;
xargs
是该转换操作符上的
args_without_in_chrg
(也就是调用时用户使用的实参),加上期望的返回类型;并且如果
subr
是
1
,表示该函数正在被递归调用(来统一一个函数的实参,或一个函数模板的函数形参);
allow_incomplete
是
1
;并且
xlen
是
-1
,表示在成功返回前,考虑所有形参;否则就是
xparms
的长度,并考虑这些实参。
9113
static
int
9114
type_unification_real
(tree tparms,
in
pt.c
9115
tree targs,
9116
tree xparms,
9117
tree xargs,
9118
int subr,
9119
unification_kind_t strict,
9120
int
allow_incomplete,
9121
int xlen)
9122
{
9123
tree parm, arg;
9124
int i;
9125
int ntparms =
TREE_VEC_LENGTH (tparms);
9126
int sub_strict;
9127
int saw_undeduced = 0;
9128
tree parms, args;
9129
int len;
9130
9131
my_friendly_assert
(TREE_CODE (tparms) == TREE_VEC, 289);
9132
my_friendly_assert (xparms
== NULL_TREE
9133
||
TREE_CODE (xparms) == TREE_LIST, 290);
9134
my_friendly_assert (!xargs
|| TREE_CODE (xargs) == TREE_LIST, 291);
9135
my_friendly_assert (ntparms
> 0, 292);
9136
9137
switch
(strict)
9138
{
9139
case
DEDUCE_CALL:
9140
sub_strict = (UNIFY_ALLOW_OUTER_LEVEL |
UNIFY_ALLOW_MORE_CV_QUAL
9141
|
UNIFY_ALLOW_DERIVED);
9142
break
;
9143
9144
case
DEDUCE_CONV:
9145
sub_strict =
UNIFY_ALLOW_LESS_CV_QUAL;
9146
break
;
9147
9148
case
DEDUCE_EXACT:
9149
sub_strict =
UNIFY_ALLOW_NONE;
9150
break
;
9151
9152
case
DEDUCE_ORDER:
9153
sub_strict =
UNIFY_ALLOW_NONE;
9154
break
;
9155
9156
default
:
9157
abort ();
9158
}
9159