您的位置:首页 > 编程语言

GCC-3.4.6源代码学习笔记(147-续2)

2011-01-22 08:43 393 查看
unify (continue)

9964

case
PTRMEM_CST:

9965

{

9966

/*
A pointer-to-member constant can be unified only with

9967

another constant.
*/

9968

if (TREE_CODE (arg) !=
PTRMEM_CST)

9969

return
1;

9970

9971

/*
Just unify the class member. It would be useless (and possibly

9972

wrong, depending on the strict flags)
to unify also

9973

PTRMEM_CST_CLASS, because we want to be
sure that both parm and

9974

arg refer to the same variable, even if
through different

9975

classes.
For instance:

9976

9977

struct A { int x; };

9978

struct B : A { };

9979

9980

Unification of &A::x and &B::x
must succeed.
*/

9981

return
unify
(tparms, targs, PTRMEM_CST_MEMBER (parm),

9982

PTRMEM_CST_MEMBER (arg),
strict);

9983

}

9984

9985

case
POINTER_TYPE:

9986

{

9987

if (TREE_CODE (arg) !=
POINTER_TYPE)

9988

return
1;

9989

9990

/*
[temp.deduct.call]

9991

9992

A
can be another pointer or pointer to member
type that can

9993

be
converted to the deduced A via a qualification

9994

conversion (_conv.qual_).

9995

9996

We
pass down STRICT here rather than UNIFY_ALLOW_NONE.

9997

This will allow for additional
cv-qualification of the

9998

pointed-to types if appropriate.
*/

9999

10000

if (TREE_CODE (TREE_TYPE
(arg)) == RECORD_TYPE)

10001

/* The derived-to-base conversion only persists through one

10002

level of pointers.
*/

10003

strict |= (strict_in
& UNIFY_ALLOW_DERIVED);

10004

10005

return
unify
(tparms, targs, TREE_TYPE (parm),

10006

TREE_TYPE
(arg), strict);

10007

}

10008

10009

case
REFERENCE_TYPE:

10010

if (TREE_CODE (arg) !=
REFERENCE_TYPE)

10011

return
1;

10012

return
unify
(tparms, targs, TREE_TYPE (parm), TREE_TYPE (arg),

10013

strict &
UNIFY_ALLOW_MORE_CV_QUAL);

10014

10015

case
ARRAY_TYPE:

10016

if (TREE_CODE (arg) !=
ARRAY_TYPE)

10017

return
1;

10018

if ((TYPE_DOMAIN (parm)
== NULL_TREE)

10019

!= (TYPE_DOMAIN
(arg) == NULL_TREE))

10020

return
1;

10021

if (TYPE_DOMAIN (parm)
!= NULL_TREE

10022

&& unify
(tparms, targs, TYPE_DOMAIN (parm),

10023

TYPE_DOMAIN
(arg), UNIFY_ALLOW_NONE) != 0)

10024

return
1;

10025

return
unify
(tparms, targs, TREE_TYPE (parm), TREE_TYPE (arg),

10026

strict &
UNIFY_ALLOW_MORE_CV_QUAL);

10027

10028

case
REAL_TYPE:

10029

case
COMPLEX_TYPE:

10030

case
VECTOR_TYPE:

10031

case
INTEGER_TYPE:

10032

case
BOOLEAN_TYPE:

10033

case
ENUMERAL_TYPE:

10034

case
VOID_TYPE:

10035

if (TREE_CODE (arg) !=
TREE_CODE (parm))

10036

return
1;

10037

10038

if (TREE_CODE (parm) ==
INTEGER_TYPE

10039

&& TREE_CODE
(TYPE_MAX_VALUE (parm)) != INTEGER_CST)

10040

{

10041

if (TYPE_MIN_VALUE
(parm) && TYPE_MIN_VALUE (arg)

10042

&& unify
(tparms, targs, TYPE_MIN_VALUE (parm),

10043

TYPE_MIN_VALUE (arg), UNIFY_ALLOW_INTEGER))

10044

return
1;

10045

if (TYPE_MAX_VALUE
(parm) && TYPE_MAX_VALUE (arg)

10046

&& unify
(tparms, targs, TYPE_MAX_VALUE (parm),

10047

TYPE_MAX_VALUE (arg),

10048

UNIFY_ALLOW_INTEGER |
UNIFY_ALLOW_MAX_CORRECTION))

10049

return
1;

10050

}

10051

/*
We have already checked cv-qualification at the top of the

10052

function.
*/

10053

else if
(!same_type_ignoring_top_level_qualifiers_p (arg, parm))

10054

return
1;

10055

10056

/*
As far as unification is concerned, this wins. Later checks

10057

will invalidate it if necessary.

*/

10058

return
0;

10059

10060

/*
Types INTEGER_CST and MINUS_EXPR can come from array bounds.
*/

10061

/*
Type INTEGER_CST can come from ordinary constant template args.
*/

10062

case
INTEGER_CST:

10063

while
(TREE_CODE (arg) == NOP_EXPR)

10064

arg = TREE_OPERAND
(arg, 0);

10065

10066

if (TREE_CODE (arg) !=
INTEGER_CST)

10067

return
1;

10068

return
!tree_int_cst_equal (parm, arg);

10069

10070

case
TREE_VEC:

10071

{

10072

int i;

10073

if (TREE_CODE (arg) !=
TREE_VEC)

10074

return
1;

10075

if (TREE_VEC_LENGTH
(parm) != TREE_VEC_LENGTH (arg))

10076

return
1;

10077

for
(i = 0; i < TREE_VEC_LENGTH (parm); ++i)

10078

if (unify
(tparms, targs,

10079

TREE_VEC_ELT
(parm, i), TREE_VEC_ELT (arg, i),

10080

UNIFY_ALLOW_NONE))

10081

return
1;

10082

return
0;

10083

}

看一下
9971
行的注释,它解释了为什么推导
PTRMEM_CST_MEMBER
,而不是整个结构。并且注意到对于标量的类型(从
REAL_TYPE

ENUMERATE_TYPE
,而
VOID_TYPE
是一个反常,它不能够被用作模板形参,但可以被传递作为缺省实参),它们对应非类型模板形参(不包括
VOID_TYPE
)。

unify (continue)

10085

case
RECORD_TYPE:

10086

case
UNION_TYPE:

10087

if (TREE_CODE (arg) !=
TREE_CODE (parm))

10088

return
1;

10089

10090

if (TYPE_PTRMEMFUNC_P
(parm))

10091

{

10092

if (!TYPE_PTRMEMFUNC_P
(arg))

10093

return
1;

10094

10095

return
unify
(tparms, targs,

10096

TYPE_PTRMEMFUNC_FN_TYPE (parm),

10097

TYPE_PTRMEMFUNC_FN_TYPE (arg),

10098

strict);

10099

}

10100

10101

if
(CLASSTYPE_TEMPLATE_INFO (parm))

10102

{

10103

tree t = NULL_TREE;

10104

10105

if (strict_in &
UNIFY_ALLOW_DERIVED)

10106

{

10107

/* First, we try to unify the PARM and ARG directly.
*/

10108

t = try_class_unification
(tparms, targs,

10109

parm, arg);

10110

10111

if (!t)

10112

{

10113

/* Fallback to the
special case allowed in

10114

[temp.deduct.call]:

10115

10116

If P is a class, and P has the form

10117

template-id, then A can be a derived class of

10118

the deduced A. Likewise, if P is a pointer to

10119

a
class of the form template-id, A can be a

10120

pointer to a derived class pointed to by the

10121

deduced A.
*/

10122

t = get_template_base
(tparms, targs,

10123

parm, arg);

10124

10125

if (! t || t ==
error_mark_node)

10126

return
1;

10127

}

10128

}

10129

else if
(CLASSTYPE_TEMPLATE_INFO (arg)

10130

&&
(CLASSTYPE_TI_TEMPLATE (parm)

10131

==
CLASSTYPE_TI_TEMPLATE (arg)))

10132

/* Perhaps PARM is something like S<U> and ARG is
S<int>.

10133

Then, we should unify `int' and `U'.
*/

10134

t = arg;

10135

else

10136

/* There's no chance of unification succeeding.
*/

10137

return
1;

10138

10139

return
unify
(tparms, targs, CLASSTYPE_TI_ARGS
(parm),

10140

CLASSTYPE_TI_ARGS (t), UNIFY_ALLOW_NONE);

10141

}

10142

else if
(!same_type_ignoring_top_level_qualifiers_p (parm, arg))

10143

return
1;

10144

return
0;

在上面的
10101
行,如果
CLASSTYPE_TEMPLATE_INFO
不是
null
,表示
parm

是一个类模板。看到在该函数的
9741
行,
strict_in

拷贝自参数
strict

,其中的
UNIFY_ALLOW_DERIVED
是,当通过函数调用推导模板实参时,在
type_unification_real

中设置的(参考在
maybe_adjust_types_for_deduction

之前的段落)。

9486

static
tree

9487

try_class_unification

(tree tparms, tree targs, tree parm, tree arg)
in pt.c

9488

{

9489

tree copy_of_targs;

9490

9491

if (!CLASSTYPE_TEMPLATE_INFO
(arg)

9492

||
(most_general_template (CLASSTYPE_TI_TEMPLATE (arg))

9493

!= most_general_template
(CLASSTYPE_TI_TEMPLATE (parm))))

9494

return
NULL_TREE;

9495

9496

/* We need to make a new template argument
vector for the call to

9497

unify.
If we used TARGS, we'd clutter it up with the result of

9498

the
attempted unification, even if this class didn't work out.

9499

We
also don't want to commit ourselves to all the unifications

9500

we've
already done, since unification is supposed to be done on

9501

an
argument-by-argument basis. In other words, consider the

9502

following
pathological case:

9503

9504

template <int I, int J, int K>

9505

struct S {};

9506

9507

template <int I, int J>

9508

struct S<I, J, 2> : public S<I, I,
I>, S<J, J, J> {};

9509

9510

template <int I, int J, int K>

9511

void f(S<I, J, K>, S<I, I, I>);

9512

9513

void g() {

9514

S<0, 0, 0> s0;

9515

S<0, 1, 2> s2;

9516

9517

f
(s0, s2);

9518

}

9519

9520

Now,
by the time we consider the unification involving `s2', we

9521

already know that we must have `f<0, 0,
0>'. But, even though

9522

`S<0, 1, 2>' is derived from `S<0,
0, 0>', the code is invalid

9523

because there are two ways to unify base
classes of S<0, 1, 2>

9524

with
S<I, I, I>. If we kept the already deduced knowledge, we

9525

would
reject the possibility I=1.
*/

9526

copy_of_targs =
make_tree_vec (TREE_VEC_LENGTH (targs));

9527

9528

/* If unification failed, we're done.
*/

9529

if (unify
(tparms, copy_of_targs, CLASSTYPE_TI_ARGS (parm),

9530

CLASSTYPE_TI_ARGS
(arg), UNIFY_ALLOW_NONE))

9531

return
NULL_TREE;

9532

9533

return
arg;

9534

}

这里有一个长的注释解释了为什么使用拷贝的模板实参的
vector
,并给出了一个作为错误的例子。进一步的,如果为在
9517
行的
f

交换
s0


s2

,这是好的代码。对于形参“
S<I, I, I>
”,“
S<0, 1, 2>
”不是好的结果,因为“
S<0, 1, 2>
”派生自“
S<0, 0, 0>
”及“
S<1, 1, 1>
”,两者都匹配“
S<I, I, I>
”这个形式。回忆【
3
】规定实参推导是以每个实参为单位进行的,在推导之后,所推导的实参应该与之前推导出的结果,或显式给定的实参相匹配。但看到这里对
unify

的调用,只是一个尝试,通过使用模板实参
vector
的拷贝,就可以不改变得到之前推导的实参。

对于上面注释中给出的例子,
s2

是不同于
S<I, I, I>
的模板,因此
try_class_unification


9494
行返回,然后进入下面的函数来检查基类是否可以统一(因为现在使用了
UNIFY_ALLOW_DERIVED
)。

9614

static
tree

9615

get_template_base

(tree tparms, tree targs, tree parm, tree arg)
in pt.c

9616

{

9617

tree rval;

9618

tree arg_binfo;

9619

9620

my_friendly_assert
(IS_AGGR_TYPE_CODE (TREE_CODE (arg)), 92);

9621

9622

arg_binfo = TYPE_BINFO (complete_type
(arg));

9623

rval = get_template_base_recursive
(tparms,
targs,

9624

parm,
arg_binfo,

9625

NULL_TREE,

9626

GTB_IGNORE_TYPE);

9627

9628

/*
Since get_template_base_recursive marks the bases classes, we

9629

must
unmark them here.
*/

9630

dfs_walk (arg_binfo,
dfs_unmark, markedp, 0);

9631

9632

return
rval;

9633

}

这个函数遍历该类的继承树,以前序在基类上执行
try_class_unification

。看到对于
s2

,其基类“
S<0, 0, 0>
”及“
S<1, 1, 1>
”依次在
9554
行进入
try_class_unification

。但是在最后一次的递归中,分别由
rval


r

所指向的,不相等的“
S<0, 0, 0>
”及“
S<1, 1, 1>
”导致该函数在
9566
行返回
error_mark_node



9540

static
tree

9541

get_template_base_recursive

(tree tparms,
in
pt.c

9542

tree
targs,

9543

tree
parm,

9544

tree
arg_binfo,

9545

tree rval,

9546

int
flags)

9547

{

9548

tree binfos;

9549

int i, n_baselinks;

9550

tree arg = BINFO_TYPE
(arg_binfo);

9551

9552

if (!(flags &
GTB_IGNORE_TYPE))

9553

{

9554

tree r = try_class_unification
(tparms, targs,

9555

parm, arg);

9556

9557

/*
If there is more than one satisfactory baseclass, then:

9558

9559

[temp.deduct.call]

9560

9561

If
they yield more than one possible deduced A, the type

9562

deduction fails.

9563

9564

applies.

*/

9565

if (r && rval
&& !same_type_p (r, rval))

9566

return
error_mark_node;

9567

else if (r)

9568

rval = r;

9569

}

9570

9571

binfos = BINFO_BASETYPES
(arg_binfo);

9572

n_baselinks = binfos ?
TREE_VEC_LENGTH (binfos) : 0;

9573

9574

/*
Process base types.
*/

9575

for
(i = 0; i < n_baselinks; i++)

9576

{

9577

tree base_binfo =
TREE_VEC_ELT (binfos, i);

9578

int this_virtual;

9579

9580

/*
Skip this base, if we've already seen it.

*/

9581

if (BINFO_MARKED
(base_binfo))

9582

continue
;

9583

9584

this_virtual =

9585

(flags &
GTB_VIA_VIRTUAL) || TREE_VIA_VIRTUAL (base_binfo);

9586

9587

/*
When searching for a non-virtual, we cannot mark virtually

9588

found binfos.
*/

9589

if (! this_virtual)

9590

BINFO_MARKED
(base_binfo) = 1;

9591

9592

rval = get_template_base_recursive
(tparms,
targs,

9593

parm,

9594

base_binfo,

9595

rval,

9596

GTB_VIA_VIRTUAL
* this_virtual);

9597

9598

/*
If we discovered more than one matching base class, we can

9599

stop
now.
*/

9600

if (rval ==
error_mark_node)

9601

return
error_mark_node;

9602

}

9603

9604

return
rval;

9605

}

回到
unify

,如果
10108
行的
try_class_unification

,或
10122
行的
get_template_base

,任一成功,表明推导是可以成功的,那么在
10139
行执行真正的推导。

而在
10142
行,对于普通类,除了最顶层的
cv-
限定词,
arg


parm

应该是同一个类型。

在下面,如
[temp.deduct.type]
的条款
3
所描述:

“一个函数类型包括该函数每个形参的类型及返回类型。

一个指向成员的指针类型包括所指向类对象的类型,及所指向成员的类型。”

这部分代码相应地处理这些情形。再下面的代码,节点
MINUS_EXPR
可能和
ARRAY_TYPE
一起来,关联的注释给出了一个清楚的解释。

unify (continue)

10146

case
METHOD_TYPE:

10147

case
FUNCTION_TYPE:

10148

if (TREE_CODE (arg) !=
TREE_CODE (parm))

10149

return
1;

10150

10151

if (unify
(tparms, targs, TREE_TYPE (parm),

10152

TREE_TYPE (arg),
UNIFY_ALLOW_NONE))

10153

return
1;

10154

return
type_unification_real
(tparms, targs,
TYPE_ARG_TYPES (parm),

10155

TYPE_ARG_TYPES (arg), 1,

10156

DEDUCE_EXACT, 0, -1);

10157

10158

case
OFFSET_TYPE:

10159

if (TREE_CODE (arg) !=
OFFSET_TYPE)

10160

return
1;

10161

if (unify
(tparms, targs, TYPE_OFFSET_BASETYPE (parm),

10162

TYPE_OFFSET_BASETYPE
(arg), UNIFY_ALLOW_NONE))

10163

return
1;

10164

return
unify
(tparms, targs, TREE_TYPE (parm), TREE_TYPE (arg),

10165

strict);

10166

10167

case
CONST_DECL:

10168

if (DECL_TEMPLATE_PARM_P
(parm))

10169

return
unify
(tparms, targs, DECL_INITIAL (parm),
arg, strict);

10170

if (arg !=
decl_constant_value (parm))

10171

return
1;

10172

return
0;

10173

10174

case
FIELD_DECL:

10175

case
TEMPLATE_DECL:

10176

/*
Matched cases are handled by the ARG == PARM test above.
*/

10177

return
1;

10178

10179

case
MINUS_EXPR:

10180

if (tree_int_cst_equal
(TREE_OPERAND (parm, 1), integer_one_node)

10181

&& (strict_in
& UNIFY_ALLOW_MAX_CORRECTION))

10182

{

10183

/* We handle this case specially, since it comes up with

10184

arrays. In particular, something like:

10185

10186

template <int N> void f(int (&x)
);

10187

10188

Here, we are trying to unify the range type, which

10189

looks like [0 ... (N - 1)].
*/

10190

tree t, t1, t2;

10191

t1 = TREE_OPERAND
(parm, 0);

10192

t2 = TREE_OPERAND
(parm, 1);

10193

10194

t = fold (build
(PLUS_EXPR, integer_type_node, arg, t2));

10195

10196

return
unify
(tparms, targs, t1,
t, strict);

10197

}

10198

/* Else fall through.
*/

10199

10200

default
:

10201

if (IS_EXPR_CODE_CLASS
(TREE_CODE_CLASS (TREE_CODE (parm))))

10202

{

10203

10204

/* We're looking at an expression. This can happen with

10205

something like:

10206

10207

template <int I>

10208

void foo(S<I>, S<I + 2>);

10209

10210

This is a "nondeduced context":

10211

10212

[deduct.type]

10213

10214

The nondeduced contexts are:

10215

10216

--A type that is a template-id in which one or more of

10217

the template-arguments is an expression that references

10218

a
template-parameter.

10219

10220

In
these cases, we assume deduction succeeded, but
don't

10221

actually infer any unifications.

*/

10222

10223

if (!uses_template_parms
(parm)

10224

&& !template_args_equal
(parm, arg))

10225

return
1;

10226

else

10227

return
0;

10228

}

10229

sorry ("use of `%s'
in template type unification",

10230

tree_code_name

[(int) TREE_CODE (parm)]);

10231

return
1;

10232

}

10233

}

最后,如果是一个构成非推导上下文的表达式,则进入
default

块。
[temp.deduct.type]

的条款
4
给出了标准的定义。这里仅是其中之一,其余的在
9789

switch

块的开头来处理。

try_one_overload (continue)

9421

/*
First make sure we didn't deduce anything that conflicts with

9422

explicitly specified args.
*/

9423

for
(i = nargs; i--; )

9424

{

9425

tree elt = TREE_VEC_ELT
(tempargs, i);

9426

tree oldelt = TREE_VEC_ELT
(orig_targs, i);

9427

9428

if (elt == NULL_TREE)

9429

continue
;

9430

else if (uses_template_parms
(elt))

9431

{

9432

/*
Since we're unifying against ourselves, we will fill in template

9433

args used in the function parm list
with our own template parms.

9434

Discard them.
*/

9435

TREE_VEC_ELT (tempargs,
i) = NULL_TREE;

9436

continue
;

9437

}

9438

else if (oldelt &&
! template_args_equal
(oldelt, elt))

9439

return
0;

9440

}

9441

9442

for
(i = nargs; i--; )

9443

{

9444

tree elt = TREE_VEC_ELT
(tempargs, i);

9445

9446

if (elt)

9447

TREE_VEC_ELT (targs, i)
= elt;

9448

}

9449

9450

return
1;

9451

}

如果这对形参
/
实参的推导成功,在这一点上,
tempargs

包含了这一次推导的实参,而
orig_targs

包含了之前推导的实参。如果两者对应的项都不为空,且不依赖于模板参数,它们必须是相同的。如果一切顺利,最后把
tempargs

中的结果合并入
targs



记得
try_one_overload

是被
resolve_overloaded_unification

调用来推导被怀疑是重载的指针的参数。而对于其他的参数,它们被
type_unification_real


9229
行的代码块处理。注意
9240
行,
len

来自参数
xlen

,如果它大于
0
,则指定了在成功返回前需要考虑的函数参数的个数。如果已成功处理所有参数,我们来到如下的代码中。

type_unification_real (continue)

9243

/* Fail if we've reached the end of the parm
list, and more args

9244

are present, and
the parm list isn't variadic.
*/

9245

if (args && args != void_list_node
&& parms == void_list_node)

9246

return
1;

9247

/* Fail if parms
are left and they don't have default values.

*/

9248

if (parms

9249

&& parms != void_list_node

9250

&& TREE_PURPOSE (parms) ==
NULL_TREE)

9251

return
1;

9252

9253

done:

9254

if (!subr)

9255

for
(i = 0;
i < ntparms; i++)

9256

if (TREE_VEC_ELT (targs, i) == NULL_TREE)

9257

{

9258

tree tparm = TREE_VALUE (TREE_VEC_ELT
(tparms, i));

9259

9260

/* If this is
an undeduced nontype parameter that depends on

9261

a
type parameter, try another pass; its type may
have been

9262

deduced
from a later argument than the one from which

9263

this
parameter can be deduced.
*/

9264

if (TREE_CODE (tparm) == PARM_DECL

9265

&& uses_template_parms
(TREE_TYPE (tparm))

9266

&& !saw_undeduced++)

9267

goto
again;

9268

9269

if (!allow_incomplete)

9270

error ("incomplete type
unification");

9271

return
2;

9272

}

9273

return
0;

9274

}

在上面
type_unification_real

的最后一部分中,在
9254
行的
subr

,如果非
0
,表示
type_unification_real

正在递归调用中,这个情形,如我们前面所见,是内层模板参数依赖于外层模板参数。但对于最外层的模板,所有的模板参数都必须被推导出来。

如果有未推导的参数,而且它是函数的形参,考虑以下例子:

template
<class
T> void func (int a[sizeof
(T)], T t) {}

int main () {

int a[sizeof
(int)];

func (a, int(5));

return
0;

}

在第一轮推导中,第一个形参无法推导出来,因为那时
T
尚未知。那么它将满足上面
9264
行的条件,通过
9267
行的
goto
语句再进行一轮推导。与上一轮不同的是,
targs

中增加了上一轮推导的结果,现在
T
已知,因而顺利地推导出第一个形参。

如果推导成功,推导出的实参被放入
targs

,那么该模板的具现将由下面的
instantiate_template

产生(记得如果该具现已经产生,这个函数只是返回这个对象)。

add_template_candidate_real (continue)

2063

if (i != 0)

2064

return
NULL;

2065

2066

fn = instantiate_template
(tmpl, targs, tf_none);

2067

if (fn == error_mark_node)

2068

return
NULL;

2069

2070

/*
In [class.copy]:

2071

2072

A
member function template is never instantiated to perform
the

2073

copy
of a class object to an object of its class type.

2074

2075

It's a
little unclear what this means; the standard explicitly

2076

does
allow a template to be used to copy a class. For example,

2077

in
:

2078

2079

struct A {

2080

A
(A&);

2081

template <class T> A(const
T&);

2082

};

2083

const A f ();

2084

void g () { A a (f ()); }

2085

2086

the
member template will be used to make the copy. The section

2087

quoted
above appears in the paragraph that forbids constructors

2088

whose
only parameter is (a possibly cv-qualified variant of) the

2089

class
type, and a logical interpretation is that the intent was

2090

to
forbid the instantiation of member templates which would then

2091

have
that form.
*/

2092

if (DECL_CONSTRUCTOR_P (fn)
&& list_length (arglist) == 2)

2093

{

2094

tree arg_types =
FUNCTION_FIRST_USER_PARMTYPE (fn);

2095

if (arg_types && same_type_p
(TYPE_MAIN_VARIANT (TREE_VALUE (arg_types)),

2096

ctype))

2097

return
NULL;

2098

}

2099

2100

if (obj != NULL_TREE)

2101

/*
Aha, this is a conversion function.
*/

2102

cand = add_conv_candidate
(candidates, fn, obj, access_path,

2103

conversion_path,
arglist);

2104

else

2105

cand = add_function_candidate
(candidates, fn,
ctype,

2106

arglist,
access_path,

2107

conversion_path,
flags);

2108

if (DECL_TI_TEMPLATE (fn) !=
tmpl)

2109

/*
This situation can occur if a member template of a template

2110

class is specialized. Then,
instantiate_template might return

2111

an
instantiation of the specialization, in which case the

2112

DECL_TI_TEMPLATE field will point at the
original

2113

specialization. For example:

2114

2115

template <class T> struct S {
template <class U> void f(U);

2116

template <>
void f(int) {}; };

2117

S<double> sd;

2118

sd.f(3);

2119

2120

Here, TMPL will be template <class
U> S<double>::f(U).

2121

And,
instantiate template will give us the specialization

2122

template <> S<double>::f(int).
But, the DECL_TI_TEMPLATE field

2123

for
this will point at template <class T> template <>
S<T>::f(int),

2124

so
that we can find the definition. For the purposes of

2125

overload resolution, however, we want the
original TMPL.
*/

2126

cand->template =
tree_cons (tmpl, targs, NULL_TREE);

2127

else

2128

cand->template =
DECL_TEMPLATE_INFO (fn);

2129

2130

return
cand;

2131

}

在【
3
】的
207
页,进一步解释了
2070
行的注释:

“因为一个模板构造函数不可能是一个拷贝构造函数,这样一个模板的存在不能压制拷贝构造函数的隐式声明。模板构造函数与其他构造函数,包括拷贝构造函数,一起参予重载解析,并且一个模板构造函数可以被用于拷贝一个对象,如果它能提供比其它构造函数更好的匹配。


通过这个检查,这个具现后的模板函数就是合资格的候选者;
2100
行的
obj


NULL
则表明是根据提供的类型,而不是对象,来找到候选者(因此
add_function_candidate

关注的是指定的源类型及目标类型,而
add_conv_candidate

则关注指定的对象及目标类型;而在这里是查找转换指定类型的函数,这就是为什么这里只调用
add_function_candidate

)。回到
build_user_type_conversion_1

,接下来的工作与找到转换操作符后的情况类似。

build_user_type_conversion_1 (continue)

2420

if (convs)

2421

args = build_tree_list
(NULL_TREE, build_this (expr));

2422

2423

for
(; convs; convs = TREE_CHAIN (convs))

2424

{

2425

tree fns;

2426

tree conversion_path =
TREE_PURPOSE (convs);

2427

int convflags =
LOOKUP_NO_CONVERSION;

2428

2429

/*
If we are called to convert to a reference type, we are trying to

2430

find
an lvalue binding, so don't even consider temporaries. If

2431

we
don't find an lvalue binding, the caller will try again to

2432

look
for a temporary binding.
*/

2433

if (TREE_CODE (totype) ==
REFERENCE_TYPE)

2434

convflags |=
LOOKUP_NO_TEMP_BIND;

2435

2436

for
(fns = TREE_VALUE (convs); fns; fns = OVL_NEXT (fns))

2437

{

2438

tree fn = OVL_CURRENT
(fns);

2439

2440

/*
[over.match.funcs] For conversion functions, the function

2441

is
considered to be a member of the class of the implicit

2442

object argument for the purpose of
defining the type of

2443

the implicit object parameter.

2444

2445

So
we pass fromtype as CTYPE to add_*_candidate.

*/

2446

2447

if (TREE_CODE (fn) ==
TEMPLATE_DECL)

2448

cand = add_template_candidate
(&candidates, fn,
fromtype,

2449

NULL_TREE,

2450

args,
totype,

2451

TYPE_BINFO
(fromtype),

2452

conversion_path,

2453

flags,

2454

DEDUCE_CONV);

2455

else

2456

cand = add_function_candidate
(&candidates, fn,
fromtype,

2457

args,

2458

TYPE_BINFO
(fromtype),

2459

conversion_path,

2460

flags);

2461

2462

if (cand)

2463

{

2464

tree ics = implicit_conversion
(totype,

2465

TREE_TYPE
(TREE_TYPE (cand->fn)),

2466

0, convflags);

2467

2468

cand->second_conv =
ics;

2469

2470

if (ics == NULL_TREE)

2471

cand->viable = 0;

2472

else if
(candidates->viable == 1 && ICS_BAD_FLAG (ics))

2473

cand->viable =
-1;

2474

}

2475

}

2476

}

不像可以作为转换转换函数的构造函数,转换操作符可以返回与目标类型不同的类型,不过它们必须可以通过
2464
行的
implicit_conversion

来匹配,而这个转换在
2468
行被记录为
second_conv

(比较对于构造函数,在
2417
行的
IDENTITY_CONV
)。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: