5.13.1.1.2.
用户定义转换序列
如果标准转换不奏效,在
implicit_conversion
的
1107
行
conv
将是
NULL
。它将要看是否有可用的用户定义的转换。这涉及重载解析的过程,【
3
】条文
13.3
“重载解析”,对此定义如下:
1. 2. — — — — — — — 3. — — 4. |
在这里我们在“
在名字出现在函数调用语法中的一个类对象(
13.3.1
.1.2
)上,调用一个函数调用操作符(
function call operator
),一个指针到函数(
pointer-to-function
)的转换函数,一个引用到指针的转换函数,或者一个引用到函数(
reference-to-function
)的转换函数;
”这个上下文中。不管怎么说,在所有上下文中解析是一样的。
5.13.1.1.2.1.
收集候选函数
C++
允许使用者在类里定义转换操作符;另外具有单个参数的,不以“
explicit
”开头的构造函数也可被用作从参数类型转换到该类类型的转换函数。
【
3
】条文
13.3.3
.1.2
“用户定义转换序列”给出了以下定义。
1. 2. 3. 4. |
2355
static
struct
z_candidate *
2356
build_user_type_conversion_1
(tree totype, tree expr, int flags)
in call.c
2357
{
2358
struct
z_candidate *candidates, *cand;
2359
tree fromtype = TREE_TYPE
(expr);
2360
tree ctors = NULL_TREE,
convs = NULL_TREE;
2361
tree args = NULL_TREE;
2362
bool any_viable_p;
2363
2364
/*
We represent conversion within a hierarchy using RVALUE_CONV and
2365
BASE_CONV, as specified by [over.best.ics];
these become plain
2366
constructor calls, as specified in
[dcl.init].
*/
2367
my_friendly_assert
(!IS_AGGR_TYPE (fromtype) || !IS_AGGR_TYPE (totype)
2368
||
!DERIVED_FROM_P (totype, fromtype), 20011226);
2369
2370
if (IS_AGGR_TYPE (totype))
2371
ctors = lookup_fnfields
(TYPE_BINFO (totype),
2372
complete_ctor_identifier
,
2373
0);
2374
2375
if (IS_AGGR_TYPE (fromtype))
2376
convs = lookup_conversions
(fromtype);
因此如果目标类型是类,收集所有定义的构造函数,因为构造函数亦可被用作转换函数。而如果源类型是类,用户定义的转换操作符就被视为候选,它们由下面的函数来收集。
2421
tree
2422
lookup_conversions
(tree type)
in
search.c
2423
{
2424
tree t;
2425
tree conversions =
NULL_TREE;
2426
2427
complete_type
(type);
2428
bfs_walk
(TYPE_BINFO (type), add_conversions
, 0,
&conversions);
2429
2430
for
(t = conversions; t; t = TREE_CHAIN (t))
2431
IDENTIFIER_MARKED (DECL_NAME (OVL_CURRENT
(TREE_VALUE (t)))) = 0;
2432
2433
return
conversions;
2434
}
在
lookup_conversions
中,
bfs_walk
里的
fn
是
add_conversions
,这个函数总是返回
NULL
从而强制完整的遍历。看到参数
data
被用于保存所有合格的候选者;而对于转换到相同类型的转换操作符,仅记录第一个被找到的。
2365
static
tree
2366
add_conversions
(tree binfo, void *data)
in
search.c
2367
{
2368
int i;
2369
tree method_vec =
CLASSTYPE_METHOD_VEC (BINFO_TYPE (binfo));
2370
tree *conversions = (tree *)
data;
2371
2372
/*
Some builtin types have no method vector, not even an empty one.
*/
2373
if (!method_vec)
2374
return
NULL_TREE;
2375
2376
for
(i = 2; i < TREE_VEC_LENGTH (method_vec); ++i)
2377
{
2378
tree tmp = TREE_VEC_ELT
(method_vec, i);
2379
tree name;
2380
2381
if (!tmp || !
DECL_CONV_FN_P (OVL_CURRENT (tmp)))
2382
break
;
2383
2384
name = DECL_NAME
(OVL_CURRENT (tmp));
2385
2386
/*
Make sure we don't already have this conversion.
*/
2387
if (! IDENTIFIER_MARKED
(name))
2388
{
2389
tree t;
2390
2391
/*
Make sure that we do not already have a conversion
2392
operator for this type. Merely checking
the NAME is not
2393
enough because two conversion operators to
the same type
2394
may not have the same NAME.
*/
2395
for
(t = *conversions; t; t = TREE_CHAIN (t))
2396
{
2397
tree fn;
2398
for
(fn = TREE_VALUE (t); fn; fn = OVL_NEXT (fn))
2399
if (same_type_p
(TREE_TYPE (name),
2400
DECL_CONV_FN_TYPE
(OVL_CURRENT (fn))))
2401
break
;
2402
if (fn)
2403
break
;
2404
}
2405
if (!t)
2406
{
2407
*conversions =
tree_cons (binfo, tmp, *conversions);
2408
IDENTIFIER_MARKED
(name) = 1;
2409
}
2410
}
2411
}
2412
return
NULL_TREE;
2413
}
在有关成员查找的章节,我们看到已经被查找过的方法会构建有
BASELINK
节点,而对于非静态方法,定义参数应该是隐含的‘
this
’指针,但对于构造函数,‘
this
’指针还没有构建,在该构造函数执行后,它才就位。因此对于构造函数,为这个隐含的参数构建一个为
NULL
的‘
this
’指针。
build_user_type_conversion_1 (continue)
2378
candidates = 0;
2379
flags |=
LOOKUP_NO_CONVERSION;
2380
2381
if (ctors)
2382
{
2383
tree t;
2384
2385
ctors = BASELINK_FUNCTIONS
(ctors);
2386
2387
t = build_int_2
(0, 0);
2388
TREE_TYPE (t) = build_pointer_type
(totype);
2389
args = build_tree_list
(NULL_TREE, expr);
2390
/*
We should never try to call the abstract or base constructor
2391
from
here.
*/
2392
my_friendly_assert
(!DECL_HAS_IN_CHARGE_PARM_P (OVL_CURRENT (ctors))
2393
&& !DECL_HAS_VTT_PARM_P
(OVL_CURRENT (ctors)),
2394
20011226);
2395
args = tree_cons
(NULL_TREE, t, args);
2396
}
2397
for
(; ctors; ctors = OVL_NEXT (ctors))
2398
{
2399
tree ctor = OVL_CURRENT
(ctors);
2400
if (DECL_NONCONVERTING_P
(ctor))
2401
continue
;
2402
2403
if (TREE_CODE (ctor) ==
TEMPLATE_DECL)
2404
cand = add_template_candidate
(&candidates,
ctor, totype,
2405
NULL_TREE, args, NULL_TREE,
2406
TYPE_BINFO
(totype),
2407
TYPE_BINFO
(totype),
2408
flags,
2409
DEDUCE_CALL);
2410
else
2411
cand = add_function_candidate
(&candidates,
ctor, totype,
2412
args,
TYPE_BINFO (totype),
2413
TYPE_BINFO
(totype),
2414
flags);
2415
2416
if (cand)
2417
cand->second_conv = build1
(IDENTITY_CONV, totype, NULL_TREE);
2418
}
5.13.1.1.2.1.1.
添加普通函数
如果该构造函数可以被作为转换函数使用(
DECL_NONCONVERTING_P
可以分辨),它们都被包括做候选。而记得如果是一个类模板,其构造函数也将是
TEMPLATE_DECL
。这样的节点由
add_template_candidate
来添加。而对于非模板方法,则是调用
add_function_candidate
。
1164
static
struct
z_candidate
*
1165
add_function_candidate
(struct
z_candidate **candidates,
in call.c
1166
tree fn,
tree ctype, tree arglist,
1167
tree
access_path, tree conversion_path,
1168
int
flags)
1169
{
1170
tree parmlist =
TYPE_ARG_TYPES (TREE_TYPE (fn));
1171
int i, len;
1172
tree convs;
1173
tree parmnode, argnode;
1174
tree orig_arglist;
1175
int viable = 1;
1176
1177
/* Built-in functions that haven't been
declared don't really
1178
exist.
*/
1179
if (DECL_ANTICIPATED (fn))
1180
return
NULL;
1181
1182
/*
The `this', `in_chrg' and VTT arguments to constructors are not
1183
considered in overload resolution.
*/
1184
if (DECL_CONSTRUCTOR_P (fn))
1185
{
1186
parmlist = skip_artificial_parms_for
(fn, parmlist);
1187
orig_arglist = arglist;
1188
arglist = skip_artificial_parms_for
(fn, arglist);
1189
}
1190
else
1191
orig_arglist = arglist;
1192
1193
len = list_length (arglist);
1194
convs = make_tree_vec (len);
1195
1196
/*
13.3.2 - Viable functions
[over.match.viable]
1197
First,
to be a viable function, a candidate function shall have enough
1198
parameters to agree in number with the
arguments in the list.
1199
1200
We
need to check this first; otherwise, checking the ICSes might cause
1201
us to
produce an ill-formed template instantiation.
*/
1202
1203
parmnode = parmlist;
1204
for
(i = 0; i < len; ++i)
1205
{
1206
if (parmnode == NULL_TREE
|| parmnode == void_list_node)
1207
break
;
1208
parmnode = TREE_CHAIN
(parmnode);
1209
}
1210
1211
if (i < len &&
parmnode)
1212
viable = 0;
1213
1214
/*
Make sure there are default args for the rest of the parms.
*/
1215
else if (!sufficient_parms_p
(parmnode))
1216
viable = 0;
1217
1218
if (! viable)
1219
goto
out;
1220
1221
/*
Second, for F to be a viable function, there shall exist for each
1222
argument an implicit conversion sequence
that converts that argument
1223
to the
corresponding parameter of F.
*/
1224
1225
parmnode = parmlist;
1226
argnode = arglist;
作为一个候选,必须是一个可行的函数调用。正如我们在前面所见,构造函数可能包括了
1
个以上的“人造”参数,其数目依赖于类的定义(它是否具有
VTT
,虚拟基类等)。
1655
tree
1656
lvalue_type
(tree arg)
in
tree.c
1657
{
1658
tree type = TREE_TYPE (arg);
1659
return
type;
1660
}
从函数的角度,参数是左值,它可以在函数体内操纵。上面的
lvalue_type
返回了
arg
的类型,当它被用作一个左值时。很可能实参的类型与对应形参的类型不相同;不过,它们必须能通过隐式转换序列来匹配。
而如果遇到了省略参数(
ellipsis parameter
),执行在
1264
行的
ELSE
块;看到这仍然需要为这个参数构建
IDENTITY_CONV
,不过设置了标记
ICS_ELLIPSIS_FLAG
来表示该
IDENTITY_CONV
用于省略参数。
add_function_candidate (continue)
1228
for
(i = 0; i < len; ++i)
1229
{
1230
tree arg = TREE_VALUE
(argnode);
1231
tree argtype = lvalue_type
(arg);
1232
tree t;
1233
int is_this;
1234
1235
if (parmnode ==
void_list_node)
1236
break
;
1237
1238
is_this = (i == 0
&& DECL_NONSTATIC_MEMBER_FUNCTION_P (fn)
1239
&& !
DECL_CONSTRUCTOR_P (fn));
1240
1241
if (parmnode)
1242
{
1243
tree parmtype = TREE_VALUE
(parmnode);
1244
1245
/*
The type of the implicit object parameter ('this') for
1246
overload resolution is not always the
same as for the
1247
function itself; conversion functions
are considered to
1248
be
members of the class being converted, and functions
1249
introduced by a using-declaration are
considered to be
1250
members of the class that uses them.
1251
1252
Since build_over_call ignores the ICS
for the `this'
1253
parameter, we can just change the parm
type.
*/
1254
if (ctype &&
is_this)
1255
{
1256
parmtype
1257
= build_qualified_type
(ctype,
1258
TYPE_QUALS
(TREE_TYPE (parmtype)));
1259
parmtype =
build_pointer_type
(parmtype);
1260
}
1261
1262
t =
implicit_conversion
(parmtype, argtype, arg, flags);
1263
}
1264
else
1265
{
1266
t = build1
(IDENTITY_CONV, argtype, arg);
1267
ICS_ELLIPSIS_FLAG (t) =
1;
1268
}
1269
1270
if (t && is_this)
1271
ICS_THIS_FLAG (t) = 1;
1272
1273
TREE_VEC_ELT (convs, i) =
t;
1274
if (! t)
1275
{
1276
viable = 0;
1277
break
;