c++ - Should name lookup be deferred for a dependent class/namespace-name in a class-member-access expression? -
the following code rejected both clang , gcc
template<typename t> void f(t t) { t.dependent::f(); // clang accepts, gcc rejects t.operator dependent*(); // both reject } struct dependent { void f(); }; struct : dependent { operator dependent*(); }; template void f<a>(a);
my reading of standard suggests both expressions should accepted.
in both cases, dependent
can type name.
in both cases, name dependent
"looked in class of object expression" t
. t
type-dependent expression, lookup should deferred until template instantiated.
is there i'm missing?
edit: if intended such name not dependent, rationale decision? can see makes life easier implementor if not have defer evaluation of construct t.operator x::dependent*
or t.x::dependent::f
x
either namespace or type name. i'm not clear on whether intended or unintended side-effect of current wording.
relevant quotes c++ working draft n3337:
3.4.5 class member access [basic.lookup.classref]
if id-expression in class member access qualified-id of form class-name-or-namespace-name::... class-name-or-namespace-name following . or -> operator first looked in class of object expression , name, if found, used. otherwise looked in context of entire postfix-expression. [ note: see 3.4.3, describes lookup of name before ::, will find type or namespace name. —end note ]
if id-expression conversion-function-id, conversion-type-id first looked in class of object expression , name, if found, used. otherwise looked in context of entire postfix-expression. in each of these lookups, only names denote types or templates specializations types considered.
14.6.2 dependent names [temp.dep]
inside template, constructs have semantics may differ 1 instantiation another. such construct depends on template parameters. in particular, types , expressions may depend on type and/or value of template parameters (as determined template arguments) , determines context name lookup names. expressions may type-dependent (on type of template parameter) or value-dependent (on value of non-type template parameter).
[...]
such names unbound , looked @ point of template instantiation (14.6.4.1) in both context of template definition , context of point of instantiation.
14.6.2.1 dependent types [temp.dep.type]
a name member of unknown specialization if is
[...]
— an id-expression denoting member in class member access expression (5.2.5) in either
— type of object expression current instantiation, current instantiation has @ least 1 dependent base class, , name lookup of id-expression not find member of current instantiation or non-dependent base class thereof; or
— the type of object expression dependent , not current instantiation.
[...]
a type dependent if is
— a member of unknown specialization,
1
here how think first case, t.dependent::f
works. first, believe (means, not totally sure) 14.6.2.1p5 should "unqualified-id" instead of "id-expression". independent of that, name dependent::f
composed out of 2 names (in standard, each nested nested-name-specifier followed member name called "qualified-id", if grammatically, these not qualified-id productions. name foo::bar::baz
qualified-id contains 1 other "qualified-id" aswell).
dependent
, dependent::f
. former not "an id-expression denoting member in class member access expression", can't apply rule applies dependent::f
apply dependent
.
dependent
therefor non-dependent , albeit need looked within dependent type have found @ definition time. think should have clause says "when looking qualified-id qualifier type-dependent, name lookup yields empty result.", handle these "force name-lookup done immediately" gracefully. anyway, in end, think first case ill-formed not finding dependent
(clause 3.4 can't decide on head of clause 14 name dependent anyway).
2
for other case, operator dependent
, things easier. again have 2 names, dependent
, operator dependent
. again, found nothing says dependent
dependent name here (i not sure whether wrong or not. that's beyond me).
name lookup comparison (say, equality function of name lookup hash table) operator function names "they conversion-function-ids formed same type" (3.8). means in order form name (not yet doing name lookup!), not have give lexical spelling case identifiers, have provide type identity, needs provided dependent
.
that lookup of dependent id-expression in t.operator dependent*
delayed means semantic type comparison delayed. try one, should work fine
struct dependent; // forward decl @ global scope t.operator dependent*(); // in function template
your followup
if intended such name not dependent, rationale decision? can see makes life easier implementor if not have defer evaluation of construct t.operator x::dependent* or t.x::dependent::f x either namespace or type name.
i don't know rationale, think have given point. looks rule skips dependent base classes when looking unqualified names. , think rationale applies case applies case aswell. makes easier reason on function template programmer, especially.
struct dependent; template<typename t> void f(t t) { t.dependent::f(); t.operator dependent*(); }
the code looks fine, if t
happens have dependent
member, dependent
have different binding (because first told t
's class, , surrounding scope). under current understanding of templating rules, above refers surrounding scope's dependent
, above code "safe", regarding pitfall.
Comments
Post a Comment