template with lambda as unique default parameter on each instantiation - c++

I'm looking for a way to automatically make default template parameter be unique each time a template is instantiated. Since unnamed function objects created by lambda expressions have different types I thought of adopting them somehow. With recent changes to standard daft removing "A lambda-expression shall not appear in ... a template-argument" restriction (see Wording for lambdas in unevaluated contexts) it seemed like a good idea. So I wrote the following kinda working snippet that compiles on recent gcc and clang:
#include <type_traits>
template<void ( * ) (void) = [](){}> class
unique final {};
static_assert(false == ::std::is_same_v<unique<>, unique<>>);
int main()
{
return 0;
}
Is this a viable approach or one of those "ill-formed, no diagnostic is required" cases?
Some additional context: I want to use this to implement Ada-style strong type definitions that should work in a single translation unit without manually inventing unique tags that would be otherwise unused:
struct _tag_WowInt {};
using Int = type<int, _tag_WowInt>;
struct _tag_SoUnique {};
using DifferentInt = type<int, _tag_SoUnique>;
Upd1: I would like to mention that approaches involving __COUNTER__ or similar macros won't work in general case because they will be expanded by preprocessor only once and won't yield unique types when used inside of template for example.

I believe that you are right, it seems to me that is "ill-formed, no diagnostic required". I think this is covered by
[temp.res/8.4] and [temp.res/8.5]:
(8.4) ― a hypothetical instantiation of a template immediately following its definition would be ill-formed due to
a construct that does not depend on a template parameter, or
(8.5) ― the interpretation of such a construct in the hypothetical instantiation is different from the interpretation
of the corresponding construct in any actual instantiation of the template. [Note: This can happen in situations including the following:
(8.5.1) ― a type used in a non-dependent name is incomplete at the point at which a template is defined but is complete at the point at which an instantiation is performed, or
(8.5.2) ― lookup for a name in the template definition found a using-declaration, but the lookup in the corresponding scope in the instantiation does not find any declarations because the using-declaration was a pack expansion and the corresponding pack is empty, or
(8.5.3) ― an instantiation uses a default argument or default template argument that had not been defined at the point at which the template was defined, or
(8.5.4) ― constant expression evaluation within the template instantiation uses
(8.5.4.1) ― the value of a const object of integral or unscoped enumeration type or
(8.5.4.2) ― the value of a constexpr object or
(8.5.4.3) ― the value of a reference or
(8.5.4.4) ― the definition of a constexpr function,
and that entity was not defined when the template was defined, or
(8.5.5) ― a class template specialization or variable template specialization that is specified by a non-dependent simple-template-id is used by the template, and either it is instantiated from a partial specialization that was not defined when the template was defined or it names an explicit specialization that was not declared when the template was defined.
— end note]
Even though your use case is not explicitly listed in the examples of the note, in my understanding the requirement implies that unique<> must refer to the same thing throughout the whole program, otherwise it is ill-formed, no diagnostic required.
This was CWG1850. The Committee appear to dislike this
kind of stateful meta-programming. The constexpr counter no longer works
in newer versions of the compilers.

Related

Name lookup in template base: why do we add this->

Consider the following:
struct Base {
void foo();
};
template <class T>
struct Derived : Base {
void bar() {
this->foo();
}
};
Typically, we explain that this-> makes foo() a dependent name, so its lookup is posponed to the second phase, i.e. to the template instantiation point.
But the second phase lookup invokes only ADL, which does not consider member functions, does it?
I'd appreciate any pointer to the Standard paragraph that explains why the above code compiles.
But the second phase lookup invokes only ADL, which does not consider member functions, does it?
It does not. However ADL adds to the lookup set, it does not comprise all of it. Also, the idea you are paraphrasing here applies to a postfix-expression in postfix-expression(args), when said postfix-expression is an unqualified-id.
[temp.dep]
1 ... In an expression of the form:
postfix-expression ( expression-listopt )
where the postfix-expression is an unqualified-id, the unqualified-id
denotes a dependent name if
[... specific conditions ...]
If an operand of an operator is a type-dependent expression, the
operator also denotes a dependent name. Such names are unbound and are
looked up at the point of the template instantiation ([temp.point]) in
both the context of the template definition and the context of the
point of instantiation.
So if you had there foo() instead, lookup would not consider members, and would instead try only free functions, both at the point of definition and instantiation (where ADL can add to the lookup set, assuming we had a dependent expression).
But for this->foo (I omitted the call intentionally, to discuss the postfix-expression), we have class member access. And here other paragraphs apply:
[temp.dep.type]
5 A name is a member of the current instantiation if it is
[...]
An id-expression denoting the member in a class member access expression for which the type of the object expression is the current instantiation, and the id-expression, when looked up, refers to at least one member of a class that is the current instantiation or a non-dependent base class thereof. [ Note: If no such member is found, and the current instantiation has any dependent base classes, then the id-expression is a member of an unknown specialization; see below.  — end note ]
6 A name is a member of an unknown specialization if it is
[...]
An id-expression denoting the member in a class member access expression in which either
the type of the object expression is the current instantiation, the current instantiation has at least one dependent base class, and name
lookup of the id-expression does not find a member of a class that is
the current instantiation or a non-dependent base class thereof; or
7 Similarly, if the id-expression in a class member access expression for which the type of the object expression is the current instantiation does not refer to a member of the current instantiation or a member of an unknown specialization, the program is ill-formed even if the template containing the member access expression is not instantiated; no diagnostic required.
These bullets tell us what lookup to perform when this->foo is encountered. It looks up members only. In our case, we have a non-dependent base class in the current instantiation, so that's where the member is to be found, unambiguously.
Having found the member function, the postfix-expression this->foo denotes a callable, and that is how the function call is resolved.
The phrase “two-phase lookup” is widely misunderstood, even among experts. C++17 said both
Such names are unbound and are looked up at the point of the template instantiation (17.6.4.1) in both the context of the template definition and the context of the point of instantiation.
(in [temp.dep]/1) and
In resolving dependent names, names from the following sources are considered:
— Declarations that are visible at the point of definition of the template.
— Declarations from namespaces associated with the types of the function arguments both from the
instantiation context (17.6.4.1) and from the definition context.
(in [temp.dep.res]/1), each of which seems to suggest that these are the two phases. However, a better way of interpreting this (unofficial) phrase is that lookup is done
from the template definition: for non-dependent names
during instantiation: from the definition but also, via ADL only, from the instantiation context
The former can be done when parsing the template definition, but no diagnostic is required for uninstantiable templates ([temp.res]/8). Note that the latter includes more than ADL.
The relevant wording has been clarified recently; it now merely says
[Note: For the part of the lookup using associated namespaces ([basic.lookup.argdep]), function declarations found in the template instantiation context are found by this lookup, as described in [basic.lookup.argdep]. — end note]
as a reminder of the difference in the second phase. Nonetheless, it confusingly uses dependent name only to refer to unqualified dependent names/operators ([temp.dep]/2). Names like Derived::foo (from the this->) are clearly dependent; as qualified names, they’re not subject to ADL, but they are still looked up during instantiation—which allows results from a dependent base to be found. (Your example has a non-dependent base, but that’s available then too.)

Why is template function of data member a dependent name only when qualifying with "this"?

struct Bar {
template<typename>
void baz() {
}
};
template<typename>
struct Foo {
Bar bar;
Foo() {
bar.baz<int>();
}
};
int main() {
return 0;
}
This code compiles fine (in GCC 4.7), but if I prefix the call to bar.baz<int>() with this->, baz becomes a dependent name that needs disambiguating with template.
bar.baz<int>(); // OK
this->bar.baz<int>(); // error
this->bar.template baz<int>(); // OK
Surely this->bar can only refer to Bar bar, whose member baz is clearly a template? Why does the addition of this-> make this code ambiguous to the compiler?
p.s. Originally, bar was a data member of a base class template which needed disambiguating with this->, but I have simplified the example for the purpose of this question.
this->bar.baz<int>(); // error
The statement above, within the definition of template<typename T> Foo<T>::Foo(), is well-formed, and should be accepted if C++11 mode or C++1y mode is enabled. But it was technically ill-formed according to C++03.
Both standards agree that this is a type-dependent expression:
C++03 14.6.2.1/1; N3690 14.6.2.1/8:
A type is dependent if it is
a template parameter,
...
a [simple-]template-id in which either the template name is a template parameter or any of the template arguments is a dependent type or an expression that is type-dependent or value-dependent,
[T is a dependent type, and so is Foo<T>.]
C++03/N3690 14.6.2.2/2:
this is type-dependent if the class type of the enclosing member function is dependent.
[Since Foo<T> is a dependent type, the expression this in its member definition is type-dependent.]
Both standards begin 14.6.2.2 with:
Except as described below, an expression is type-dependent if any subexpression is type-dependent.
C++03 has only three simple categories of expressions with more exact descriptions:
Primary expressions (this and looked-up names)
Expressions that specify their own type (like casts and new-expressions)
Expressions with constant type (like literals and sizeof).
The first category is defined in C++03 14.6.2.2/3:
An id-expression is type-dependent if it contains:
an identifier that was declared with a dependent type,
a template-id that is dependent,
a conversion-function-id that specifies a dependent type,
a nested-name-specifier that contains a class-name that names a dependent type.
So the lone expression bar is not dependent: it is an identifier and an id-expression, but none of the above apply.
But this->bar is not an id-expression, or in any of the other C++03 exceptions, so we have to follow the subexpression rule. Since subexpression this is type-dependent, the containing expression this->bar is also type-dependent.
But in fact, as you noticed, the type of this->bar can be known while parsing the template definition, without instantiating any template arguments. It is declared as a member of the primary template, so the name must bind to that member declaration. A template specialization might make Foo<T>::bar undeclared or declared in a different way, but in that case the primary template won't be used at all and the current definition of Foo() is ignored for that specialization. Which is why C++11 defined the concept of "the current instantiation" and used it for a further exception to the contagiousness of type-dependent expressions.
N3690 14.6.2.1/1:
A name refers to the current instantiation if it is
in the definition of a class template, a nested class of a class template, a member of a class template, or a member of a nested class of a class template, the injected-class-name of the class template or nested class
in the definition of a primary class template or a member of a primary class template, the name of the class template followed by the template argument list of the primary template (as described below) enclosed in <> (or an equivalent template alias specialization),
...
[The first bullet says Foo is the current instantiation. The second says Foo<T> is the current instantiation. In this example, both name the same type.]
14.6.2.1/4:
A name is a member of the current instantiation if it is
An unqualified name that, when looked up, refers to at least one member of a class that is the current instantiation or a non-dependent base class thereof.
A qualified-id in which ...
An id-expression denoting the member in a class member access expression for which the type of the object expression is the current instantiation, and the id-expression, when looked up, refers to at least one member of a class that is the current instantiation or a non-dependent base class thereof.
[The first bullet says bar alone is a member of the current instantiation. The third bullet says this->bar is a member of the current instantiation.]
Finally, C++11 adds a fourth category of rules for type-dependent expressions, for member access. 14.6.2.2/5:
A class member access expression is type-dependent if the expression refers to a member of the current instantiation and the type of the referenced member is dependent, or the class member access expression refers to a member of an unknown specialization.
this->bar does refer to a member of the current instantiation, but the type Bar of the referenced member is not dependent. So now this->bar is not type-dependent, and the name baz in this->bar.baz is looked up during the template definition as a non-dependent name. The template keyword is not needed before baz.
Short summary
This is just the way the current C++11 rules are: this->bar.baz<int>() introduces a dependent name not in the current instantiation context that requires disambiguation with the template keyword, even though it is very hard to come up with an actual example of a competing parse that change the semantics of the expression this->bar.baz<int>().
Parsing ambiguity from angle brackets
First: why in general is there a need for template?
When a C++ compiler encounters an expression f<g>(0), it can interpret this either as "call the function template f for template argument g and function argument 0 and evaluate the result" or it can mean "make the comparison (f<g)>(0) for names f and g and constant 0." Without further information it cannot make this decision. This is an unfortunate consequence of the choice of angle brackets for template arguments.
In many (most) cases, the compiler does have enough context to decide whether a template expression or a comparison is being parsed. However, when a so-called dependent name (essentially a name that is explicitly or implicitly dependent on a template parameter of the current scope) is encountered, another language subtlety comes into play.
Two-phase name lookup
Because a name dependent on a template could change its meaning (e.g. through specializations) when a template is being instantiated for a concrete type, name lookup of dependent names is done in two phases (quote from C++ Templates the Complete Guide):
During the first phase, nondependent names are looked up while the
template is being parsed using both the ordinary lookup rules and, if
applicable, the rules for argument-dependent lookup (ADL).
Unqualified dependent names (which are dependent because they look like the name of a function in a function call with dependent
arguments) are also looked up that way, but the result of the lookup
is not considered complete until an additional lookup is performed
when the template is instantiated.
During the second phase, which occurs when templates are instantiated
at a point called the point of instantiation (POI), dependent
qualified names are looked up (with the template parameters replaced
with the template arguments for that specific instantiation), and an
additional ADL is performed for the unqualified dependent names.
Why this-> makes your code different
Using this-> inside a class template introduces a dependent name and triggers two-phase name lookup. In that case, the rule cited by #40two comes into play. The point is that the ADL at the 2nd phase can bring in new names from explicit specializations that redefine the meaning of your bar and baz and it could conceivably change the meaning of this->bar.baz<int>(0) to a comparison rather than a function template call.
Granted, for non-type template arguments such as this->bar.another_baz<0>() this would be more likely than for a type template parameter. In this related Q&A a similar discussion arose whether one could find a syntactic valid form that changes the meaning of this->f<int>() vs this->template f<int>(0), without a clear conclusion.
Note that C++11 already relaxes the rule for template disambiguation compared to C++98. Under the current rules this->f<int>() for a template<class> f() inside Foo would not require template because it is in the so-called current instantiation. See this answer from the canonical Q&A for this topic for more details
According to the standard § 14.2/4 Names of template specializations [temp.names]
When the name of a member template specialization appears after . or -> in a postfix-expression or after a nested-name-specifier in a qualified-id, and the object expression of the postfix-expression is type-dependent or the nested-name-specifier in the qualified-id refers to a dependent type, but the name is not a member of the current instantiation (14.6.2.1), the member template name must be prefixed by the keyword template.
Edit:
Also, according the standard § 14.6.2.2/2 Type-dependent expressions [temp.dep.expr]:
this is type-dependent if the class type of the enclosing member function is dependent (14.6.2.1).
Thus, in order to call bar.baz<int>() via this you need to prefixed by the keyword template:
this->bar.template baz<int>();
LIVE DEMO
[Reason:]
The compiler needs this "redantant" use of template keyword, because it can't decide whether the token < is operator< or the beginning of a template argument list.

Example of non odr-used variable defined in the program [duplicate]

This just came up in the context of another question.
Apparently member functions in class templates are only instantiated if they are ODR-used.
Could somebody explain what exactly that means. The wikipedia article on One Definition Rule (ODR) doesn't mention "ODR-use".
However the standard defines it as
A variable whose name appears as a potentially-evaluated expression
is odr-used unless it is an object that satisfies the requirements for
appearing in a constant expression (5.19) and the lvalue-to-rvalue
conversion (4.1) is immediately applied.
in [basic.def.odr].
Edit: Apparently this is the wrong part and the entire paragraph contains multiple definitions for different things. This might be the relevant one for class template member function:
A non-overloaded function whose name appears as a
potentially-evaluated expression or a member of a set of candidate
functions, if selected by overload resolution when referred to from a
potentially-evaluated expression, is odr-used, unless it is a pure
virtual function and its name is not explicitly qualified.
I do however not understand, how this rule works across multiple compilation units? Are all member functions instantiated if I explicitly instantiate a class template?
It's just an arbitrary definition, used by the standard to
specify when you must provide a definition for an entity (as
opposed to just a declaration). The standard doesn't say just
"used", because this can be interpreted diversely depending on
context. And some ODR-use doesn't really correspond to what one
would normally associate with "use"; for example, a virtual
function is always ODR-used unless it is pure, even if it isn't
actually called anywhere in the program.
The full definition is in §3.2, second paragraph, although this
contains references to other sections to complete the
definition.
With regards to templates, ODR-used is only part of question;
the other part is instantiation. In particular, §14.7 covers
when a template is instantiated. But the two are related: while
the text in §14.7.1 (implicit instantiation) is fairly long, the
basic principle is that a template will only be instantiated if
it is used, and in this context, used means ODR-used. Thus,
a member function of a class template will only be instantiated
if it is called, or if it is virtual and the class itself is
instantiated. The standard itself counts on this in many
places: the std::list<>::sort uses < on the individual
elements, but you can instantiate a list over an element type
which doesn't support <, as long as you don't call sort on
it.
In plain word, odr-used means something(variable or function) is used in a context where the definition of it must be present.
e.g.,
struct F {
static const int g_x = 2;
};
int g_x_plus_1 = F::g_x + 1; // in this context, only the value of g_x is needed.
// so it's OK without the definition of g_x
vector<int> vi;
vi.push_back( F::g_x ); // Error, this is odr-used, push_back(const int & t) expect
// a const lvalue, so it's definition must be present
Note, the above push_back passed in MSVC 2013. This behavior is not standard compliant - both gcc 4.8.2 and clang 3.8.0 failed, with error message:
undefined reference to F::g_x

What does it mean to "ODR-use" something?

This just came up in the context of another question.
Apparently member functions in class templates are only instantiated if they are ODR-used.
Could somebody explain what exactly that means. The wikipedia article on One Definition Rule (ODR) doesn't mention "ODR-use".
However the standard defines it as
A variable whose name appears as a potentially-evaluated expression
is odr-used unless it is an object that satisfies the requirements for
appearing in a constant expression (5.19) and the lvalue-to-rvalue
conversion (4.1) is immediately applied.
in [basic.def.odr].
Edit: Apparently this is the wrong part and the entire paragraph contains multiple definitions for different things. This might be the relevant one for class template member function:
A non-overloaded function whose name appears as a
potentially-evaluated expression or a member of a set of candidate
functions, if selected by overload resolution when referred to from a
potentially-evaluated expression, is odr-used, unless it is a pure
virtual function and its name is not explicitly qualified.
I do however not understand, how this rule works across multiple compilation units? Are all member functions instantiated if I explicitly instantiate a class template?
It's just an arbitrary definition, used by the standard to
specify when you must provide a definition for an entity (as
opposed to just a declaration). The standard doesn't say just
"used", because this can be interpreted diversely depending on
context. And some ODR-use doesn't really correspond to what one
would normally associate with "use"; for example, a virtual
function is always ODR-used unless it is pure, even if it isn't
actually called anywhere in the program.
The full definition is in §3.2, second paragraph, although this
contains references to other sections to complete the
definition.
With regards to templates, ODR-used is only part of question;
the other part is instantiation. In particular, §14.7 covers
when a template is instantiated. But the two are related: while
the text in §14.7.1 (implicit instantiation) is fairly long, the
basic principle is that a template will only be instantiated if
it is used, and in this context, used means ODR-used. Thus,
a member function of a class template will only be instantiated
if it is called, or if it is virtual and the class itself is
instantiated. The standard itself counts on this in many
places: the std::list<>::sort uses < on the individual
elements, but you can instantiate a list over an element type
which doesn't support <, as long as you don't call sort on
it.
In plain word, odr-used means something(variable or function) is used in a context where the definition of it must be present.
e.g.,
struct F {
static const int g_x = 2;
};
int g_x_plus_1 = F::g_x + 1; // in this context, only the value of g_x is needed.
// so it's OK without the definition of g_x
vector<int> vi;
vi.push_back( F::g_x ); // Error, this is odr-used, push_back(const int & t) expect
// a const lvalue, so it's definition must be present
Note, the above push_back passed in MSVC 2013. This behavior is not standard compliant - both gcc 4.8.2 and clang 3.8.0 failed, with error message:
undefined reference to F::g_x

Should name lookup be deferred for a dependent class/namespace-name in a class-member-access expression?

The following code is rejected by both clang and 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 A : Dependent
{
operator Dependent*();
};
template void f<A>(A);
My reading of the standard suggests both expressions should be accepted.
In both cases, Dependent can only be a type name.
In both cases, the name Dependent is to be "looked up in the class of the object expression" t. As t is a type-dependent expression, the lookup should be deferred until the template is instantiated.
Is there something I'm missing?
EDIT: If it is intended that such a name is not dependent, what is the rationale for this decision? I can see that it makes life easier for the implementor if they do not have to defer evaluation of a construct like t.operator X::Dependent* or t.X::Dependent::f where X could be either a namespace or a type name. I'm not clear on whether this is an intended or unintended side-effect of the current wording.
Relevant quotes from C++ Working Draft N3337:
3.4.5 Class member access [basic.lookup.classref]
If the id-expression in a class member access is a qualified-id of the form
class-name-or-namespace-name::...
the class-name-or-namespace-name following the . or -> operator is first looked up in the class of the
object expression and the name, if found, is used. Otherwise it is looked up in the context of the entire
postfix-expression. [ Note: See 3.4.3, which describes the lookup of a name before ::, which will only find a
type or namespace name. —end note ]
If the id-expression is a conversion-function-id, its conversion-type-id is first looked up in the class of the
object expression and the name, if found, is used. Otherwise it is looked up in the context of the entire
postfix-expression. In each of these lookups, only names that denote types or templates whose specializations
are types are considered.
14.6.2 Dependent names [temp.dep]
Inside a template, some constructs have semantics which may differ from one instantiation to another. Such a
construct depends on the template parameters. In particular, types and expressions may depend on the type
and/or value of template parameters (as determined by the template arguments) and this determines the
context for name lookup for certain names. Expressions may be type-dependent (on the type of a template
parameter) or value-dependent (on the value of a non-type template parameter).
[...]
Such names are unbound and are looked up at the point of the template instantiation (14.6.4.1) in both the
context of the template definition and the context of the point of instantiation.
14.6.2.1 Dependent types [temp.dep.type]
A name is a member of an unknown specialization if it is
[...]
— An id-expression denoting the member in a class member access expression (5.2.5) in which either
— the type of the object expression is the current instantiation, the current instantiation has at least
one dependent base class, and name lookup of the id-expression does not find a member of the
current instantiation or a non-dependent base class thereof; or
— the type of the object expression is dependent and is not the current instantiation.
[...]
A type is dependent if it is
— a member of an unknown specialization,
1
Here is how I think your first case, t.Dependent::f works. First, I believe (means, I am not totally sure) that 14.6.2.1p5 should say "unqualified-id" instead of "id-expression". But independent of that, your name Dependent::f is actually composed out of two names (in the Standard, each nested nested-name-specifier followed by a member name is called "qualified-id", even if grammatically, these are not qualified-id productions. So a name foo::bar::baz is a qualified-id but also contains 1 other "qualified-id" aswell).
Dependent and Dependent::f. The former is not "An id-expression denoting the member in a class member access expression", so you can't simply apply the rule that applies to Dependent::f to apply also to Dependent.
Dependent is therefor non-dependent and albeit it will need to be looked up within a dependent type will have to be found at definition time. I personally think that we should have a clause that says "When looking up a qualified-id where the qualifier is type-dependent, name lookup yields an empty result.", to handle these "force name-lookup to be done immediately" gracefully. So anyway, in the end, I think your first case is ill-formed by not finding Dependent (clause 3.4 can't just decide by itself over the head of clause 14 that the name is actually dependent anyway).
2
For your other case, operator Dependent, things are easier. You again have two names, Dependent and operator Dependent. Again, I found nothing that says that Dependent is a dependent name here (I am not sure whether that would be wrong or not. That's beyond me).
Name lookup comparison (say, the equality function of the name lookup hash table) for operator function names is "they are conversion-function-ids formed with the same type" (3.8). This means that in order to form the name itself (not yet doing name lookup!), you not only have to give the lexical spelling as is the case for identifiers, but you have to provide a type identity, which needs to be provided by Dependent.
That the lookup of the dependent id-expression in t.operator Dependent* is delayed simply means that the semantic type comparison is delayed. Try this one, which should work fine
struct Dependent; // forward decl at global scope
t.operator Dependent*(); // in function template
Your followup
If it is intended that such a name is not dependent, what is the rationale for this decision? I can see that it makes life easier for the implementor if they do not have to defer evaluation of a construct like t.operator X::Dependent* or t.X::Dependent::f where X could be either a namespace or a type name.
I don't know the rationale, but I think you already have given a good point. This looks very much to the rule that skips dependent base classes when looking up unqualified names. And I think what rationale applies for that case applies for this case aswell. It makes it easier to reason on the function template for the programmer, especially.
struct Dependent;
template<typename T>
void f(T t)
{
t.Dependent::f();
t.operator Dependent*();
}
The code looks fine, but if T happens to have a Dependent member, suddenly Dependent would have a different binding (because first we are told to look into t's class, and then into the surrounding scope). Under my current understanding of the templating rules, the above always refers to the surrounding scope's Dependent, so the above code is "safe", regarding to that pitfall.