Saturday 15 May 2010

c++ - Where and why do I have to put the "template" and "typename" keywords? -



c++ - Where and why do I have to put the "template" and "typename" keywords? -

in templates, , why have set typename , template on dependent names? dependent names anyway? have next code:

template <typename t, typename tail> // tail unionnode too. struct unionnode : public tail { // ... template<typename u> struct inunion { // q: add together typename/template here? typedef tail::inunion<u> dummy; }; template< > struct inunion<t> { }; }; template <typename t> // lastly node tn. struct unionnode<t, void> { // ... template<typename u> struct inunion { char fail[ -sizeof(u) ]; // cannot instantiated u }; template< > struct inunion<t> { }; };

the problem have in typedef tail::inunion<u> dummy line. i'm inunion dependent name, , vc++ quite right in choking on it. know should able add together template somewhere tell compiler inunion template-id. exactly? , should assume inunion class template, i.e. inunion<u> names type , not function?

in order parse c++ program, compiler needs know names whether types or not. next illustration demonstrates that:

t * f;

how should parsed? many languages compiler doesn't need know meaning of name in order parse , know action line of code does. in c++, above can yield vastly different interpretations depending on t means. if it's type, declaration of pointer f. if it's not type, multiplication. c++ standard says @ paragraph (3/7):

some names denote types or templates. in general, whenever name encountered necessary determine whether name denotes 1 of these entities before continuing parse programme contains it. process determines called name lookup.

how compiler find out name t::x refers to, if t refers template type parameter? x static int info fellow member multiplied or as nested class or typedef yield declaration. if name has property - can't looked until actual template arguments known - it's called dependent name (it "depends" on template parameters).

you might recommend wait till user instantiates template:

let's wait until user instantiates template, , later find out real meaning of t::x * f;.

this work , allowed standard possible implementation approach. these compilers re-create template's text internal buffer, , when instantiation needed, parse template , perchance observe errors in definition. instead of bothering template's users (poor colleagues!) errors made template's author, other implementations take check templates on , give errors in definition possible, before instantiation takes place.

so there has way tell compiler names types , names aren't.

the "typename" keyword

the reply is: we decide how compiler should parse this. if t::x dependent name, need prefix typename tell compiler parse in way. standard says @ (14.6/2):

a name used in template declaration or definition , dependent on template-parameter assumed not name type unless applicable name lookup finds type name or name qualified keyword typename.

there many names typename not necessary, because compiler can, applicable name lookup in template definition, figure out how parse build - illustration t *f;, when t type template parameter. t::x * f; declaration, must written typename t::x *f;. if omit keyword , name taken non-type, when instantiation finds denotes type, usual error messages emitted compiler. sometimes, error consequently given @ definition time:

// t::x taken non-type, look next misses // operator between 2 names or semicolon separating them. t::x f;

the syntax allows typename before qualified names - therefor taken granted unqualified names known refer types if so.

a similar gotcha exists names denote templates, hinted @ introductory text.

the "template" keyword

remember initial quote above , how standard requires special handling templates well? let's take next innocent-looking example:

boost::function< int() > f;

it might obvious human reader. not compiler. imagine next arbitrary definition of boost::function , f:

namespace boost { int function = 0; } int main() { int f = 0; boost::function< int() > f; }

that's valid expression! compares boost::function 0 (int()), , compares resulting bool against f. might know, boost::function in real life template, compiler knows (14.2/3):

after name lookup (3.4) finds name template-name, if name followed <, < taken origin of template-argument-list , never name followed less-than operator.

now same problem typename. if can't know yet whether name template when parsing code? need insert template before template name, specified 14.2/4. looks like:

t::template f<int>(); // phone call function template

template names can not occur after :: after -> or . in class fellow member access. need insert keyword there too:

this->template f<int>(); // phone call function template dependencies

for people have thick standardese books on shelf , want know talking about, i'll talk bit how specified in standard.

in template declarations constructs have different meanings depending on template arguments utilize instantiate template: expressions may have different types or values, variables may have different types or function calls might end calling different functions. such constructs said depend on template parameters.

the standard defines exactly rules whether build dependent or not. separates them logically different groups: 1 catches types, catches expressions. expressions may depend value and/or type. have, typical examples appended:

dependent types (e.g: type template parameter t) value-dependent expressions (e.g: non-type template parameter n) type-dependent expressions (e.g: cast type template parameter (t)0)

most of rules intuitive , built recursively: example, type constructed t[n] dependent type if n value-dependent look or t dependent type. details of can read in section (14.6.2/1) dependent types, (14.6.2.2) type-dependent expressions , (14.6.2.3) value-dependent expressions.

dependent names

the standard bit unclear exactly dependent name. on simple read (you know, principle of to the lowest degree surprise), defines dependent name special case function names below. since t::x needs looked in instantiation context, needs dependent name (fortunately, of mid c++14 commission has started how prepare confusing definition).

to avoid problem, have resorted simple interpretation of standard text. of constructs denote dependent types or expressions, subset of them represent names. names hence "dependent names". name can take different forms - standard says:

a name utilize of identifier (2.11), operator-function-id (13.5), conversion-function-id (12.3.2), or template-id (14.2) denotes entity or label (6.6.4, 6.1)

an identifier plain sequence of characters / digits, while next 2 operator + , operator type form. lastly form template-name <argument list>. these names, , conventional utilize in standard, name can include qualifiers namespace or class name should looked in.

a value dependent look 1 + n not name, n is. subset of dependent constructs names called dependent name. function names, however, may have different meaning in different instantiations of template, unfortunately not caught general rule.

dependent function names

not concern of article, still worth mentioning: function names exception handled separately. identifier function name dependent not itself, type dependent argument expressions used in call. in illustration f((t)0), f dependent name. in standard, specified @ (14.6.2/1).

additional notes , examples

in plenty cases need both of typename , template. code should following

template <typename t, typename tail> struct unionnode : public tail { // ... template<typename u> struct inunion { typedef typename tail::template inunion<u> dummy; }; // ... };

the keyword template doesn't have appear in lastly part of name. can appear in middle before class name that's used scope, in next example

typename t::template iterator<int>::value_type v;

in cases, keywords forbidden, detailed below

on name of dependent base of operations class not allowed write typename. it's assumed name given class type name. true both names in base-class list , constructor initializer list:

template <typename t> struct derive_from_has_type : /* typename */ somebase<t>::type { };

in using-declarations it's not possible utilize template after lastly ::, , c++ commission said not work on solution.

template <typename t> struct derive_from_has_type : somebase<t> { using somebase<t>::template type; // error using typename somebase<t>::type; // typename *is* allowed };

c++ templates typename c++-faq dependent-name

No comments:

Post a Comment