然后如果一切顺利,最后通过
10401
的
fn_type_unifcation
把推导后实参放入
targs
。而这些实参接着在
resolve_overloaded_unification
的
9334
行,立即由
tsubst
替代入模板形参。
接着在下面的函数中,
tparms
指向模板形参;
orig_targs
是推导出的实参的
vector
;两者都是调用者
resolve_overloaded_unification
的参数
tparms
及
targs
,并且在下面的过程中都不会改变。而
targs
是
orig_tags
的拷贝;
parm
是模板形参;
arg
则是相应的模板实参(在这里它们是函数指针类型);而
addr_p
如果是
true
,表示看到“
&
”。
9380
static
int
9381
try_one_overload
(tree tparms,
in
pt.c
9382
tree
orig_targs,
9383
tree targs,
9384
tree parm,
9385
tree arg,
9386
unification_kind_t strict,
9387
int sub_strict,
9388
bool addr_p)
9389
{
9390
int nargs;
9391
tree tempargs;
9392
int i;
9393
9394
/*
[temp.deduct.type] A template-argument can be deduced from a pointer
9395
to function or pointer to member function
argument if the set of
9396
overloaded functions does not contain
function templates and at most
9397
one of
a set of overloaded functions provides a unique match.
9398
9399
So if
this is a template, just return success.
*/
9400
9401
if (uses_template_parms
(arg))
9402
return
1;
9403
9404
if (TREE_CODE (arg) ==
METHOD_TYPE)
9405
arg =
build_ptrmemfunc_type (build_pointer_type
(arg));
9406
else if (addr_p)
9407
arg = build_pointer_type
(arg);
9408
9409
sub_strict |= maybe_adjust_types_for_deduction
(strict, &parm, &arg);
当使用指向函数指针(
pointer-to-function
)或指向方法指针(
pointer-to-method
)的模板形参时,我们可以仅使用“
&A::f
”或“
&f
”(对于函数,还可以使用“
f
”)及
typedef
别名作为实参,因为前端要求编译时的常量。因此上面,在看到这样的结构后,构建相应的指针。
【
3
】的
[temp.deduct.conv]
定义到“模板实参推导,通过模板转换函数的返回类型
(称之为
P
)与作为转换结果所要求的类型(称之为
A
)的比较,如
14.8.2
.4
所示,来完成。
”
而
[temp.deduct.call]
提到:“模板实参推导,通过所下所示的,比较每个函数模板形参类型
(称之为
P
)与调用的对应实参类型(称之为
A
),来完成
”。
记住对于转换操作符,已经把该操作符的返回类型加入到了形参列表,被期望的类型加入到了实参列表。并且看到在该操作符的调用点,它将尝试把返回类型转换为被期望的类型(即从形参到实参,而不是像函数参数那样从实参到形参)。因此下面的函数首先通过
DEDUCE_CONV
交换了这两者(现在,对于转换操作符的规则,
P
变成了
A
,
A
变成了
P
)。进一步的,【
3
】有如下定义:
来自 2. — — — 如果 来自 2. — — — 如果 来自 3. — — A — 仅当类型推导没有其它选择,才考虑这些替代方案。如果它们产生多于一个可能的推导的 来自 3. — — 仅当类型推导没有其它选择,才考虑这些替代方案。如果它们产生多于一个可能的推导的 |
看到通过交换
arg
与
parm
,可以把
[temp.deduct.call]
的第二个规则同时用于函数调用及转换操作符,而不需作出改变。而对于
[temp.deduct.call]
及
[temp.deduct.conv]
的第三个规则,观察下面的例子:
例
1
:
template
<class
T> void func (const
T&);
// const T& is P
int a;
main () { func (a); }
// const int is deduced A, and A is int
类
2
:
template
<typename
T> class
A {
public
:
T i;
operator
T& () { return
i; }
// operator const T& () { return i; } // const
int& is P (A after swap)
in
A<int> a
};
void func (const
int&) {}
// const
int& is A (P after swap)
// void func (int&) {}
// int& is A (P after swap)
main () {
A<int> a;
// int& is P
(A after swap)
func (a);
// int is deduced A, const int is deduced A for commented
out operator
}
如果恢复上面注掉的语句,将导致
cv-
限定冲突的错误。可以看到对于转换操作符,通过交换
parm
及
arg
,我们可以安全地为函数调用及转换操作符,统一使用推导函数调用的规则
3
中的前两个替代方案。而对于函数调用规则
3
中的第三个替代方案,前端可以通过不设定标记
UNIFY_ALLOW_DERIVED
,来为转换操作符避免它。
9007
static
int
9008
maybe_adjust_types_for_deduction
(unification_kind_t strict,
in pt.c
9009
tree* parm,
9010
tree* arg)
9011
{
9012
int result = 0;
9013
9014
switch
(strict)
9015
{
9016
case
DEDUCE_CALL:
9017
break
;
9018
9019
case
DEDUCE_CONV:
9020
{
9021
/*
Swap PARM and ARG throughout the remainder of this
9022
function; the handling is precisely
symmetric since PARM
9023
will initialize ARG rather than vice
versa.
*/
9024
tree* temp = parm;
9025
parm = arg;
9026
arg = temp;
9027
break
;
9028
}
9029
9030
case
DEDUCE_EXACT:
9031
/*
There is nothing to do in this case.
*/
9032
return
0;
9033
9034
case
DEDUCE_ORDER:
9035
/*
DR 214. [temp.func.order] is underspecified, and leads to no
9036
ordering between things like `T *' and
`T const &' for `U *'.
9037
The former has T=U and the latter T=U*.
The former looks more
9038
specialized and John Spicer considers
it well-formed (the EDG
9039
compiler accepts it).
9040
9041
John also confirms that deduction
should proceed as in a function
9042
call. Which implies the usual ARG and
PARM conversions as DEDUCE_CALL.
9043
However, in ordering, ARG can have
REFERENCE_TYPE, but no argument
9044
to
an actual call can have such a type.
9045
9046
If
both ARG and PARM are REFERENCE_TYPE, we change neither.
9047
If
only ARG is a REFERENCE_TYPE, we look through that and then
9048
proceed as with DEDUCE_CALL (which
could further convert it).
*/
9049
if (TREE_CODE (*arg) ==
REFERENCE_TYPE)
9050
{
9051
if (TREE_CODE (*parm)
== REFERENCE_TYPE)
9052
return
0;
9053
*arg = TREE_TYPE
(*arg);
9054
}
9055
break
;
9056
default
:
9057
abort ();
9058
}
9059
9060
if (TREE_CODE (*parm) !=
REFERENCE_TYPE)
9061
{
9062
/* [temp.deduct.call]
9063
9064
If P
is not a reference type:
9065
9066
--If
A is an array type, the pointer type produced by the
9067
array-to-pointer standard conversion
(_conv.array_) is
9068
used in place of A for type deduction;
otherwise,
9069
9070
--If
A is a function type, the pointer type produced by
9071
the
function-to-pointer standard conversion
9072
(_conv.func_) is used in place of A for
type deduction;
9073
otherwise,
9074
9075
--If
A is a cv-qualified type, the top level
9076
cv-qualifiers of A's type are ignored
for type
9077
deduction.
*/
9078
if (TREE_CODE (*arg) ==
ARRAY_TYPE)
9079
*arg = build_pointer_type
(TREE_TYPE (*arg));
9080
else if (TREE_CODE (*arg)
== FUNCTION_TYPE)
9081
*arg = build_pointer_type
(*arg);
9082
else
9083
*arg = TYPE_MAIN_VARIANT
(*arg);
9084
}
9085
9086
/*
[temp.deduct.call]
9087
9088
If P
is a cv-qualified type, the top level cv-qualifiers
9089
of P's
type are ignored for type deduction. If P is a
9090
reference type, the type referred to by P
is used for
9091
type
deduction.
*/
9092
*parm = TYPE_MAIN_VARIANT
(*parm);
9093
if (TREE_CODE (*parm) ==
REFERENCE_TYPE)
9094
{
9095
*parm = TREE_TYPE (*parm);
9096
result |=
UNIFY_ALLOW_OUTER_MORE_CV_QUAL;
9097
}
9098
9099
/* DR 322. For conversion deduction, remove a
reference type on parm
9100
too
(which has been swapped into ARG).
*/
9101
if (strict == DEDUCE_CONV
&& TREE_CODE (*arg) == REFERENCE_TYPE)
9102
*arg = TREE_TYPE (*arg);
9103
9104
return
result;
9105
}
那么函数
maybe_adjust_types_for_deduction
根据上面表中由【
3
】指定规则转换实参。
9035
行的注释提及了【
3
】中的一个瑕疵,并给出了
EDG
(最好的
C++
前端)所采纳的一个可能的解决方案。
try_one_overload (continue)
9411
/*
We don't copy orig_targs for this because if we have already deduced
9412
some
template args from previous args, unify would complain when we
9413
try to
deduce a template parameter for the same argument, even though
9414
there
isn't really a conflict.
*/
9415
nargs = TREE_VEC_LENGTH (targs);
9416
tempargs = make_tree_vec
(nargs);
9417
9418
if (unify
(tparms, tempargs, parm, arg, sub_strict) != 0)
9419
return
0;
【
3
】的条文
14.8.2
.4
“从一个类型推导模板实参”如下所示
[temp.deduct.type
]
:
1. 2. 3. — — — — 在大多数情况下,构成 4. — —一个 当一个类型的名字在以一个包含非推导上下文的方式指定时,所有组成这个类型名的类型也都是非推导的。不过,一个复合类型( 5. template struct struct int g(A a, B b) { f(a,b); // error: T could be A or B f(b,a); // error: T could be A or B f(a,a); // OK: T is A f(b,b); // OK: T is B } 6. template int g1( int, float, float); char g2( int, float, float); int g3( int, char, float); void r() { f(g1); // OK: T is int and U is float f(g2); // error: T could be char or int f(g3); // error: U could be char or } 7. template int *p; void s() { f(p); // f(const int *) } 8. template |