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


in templates, , why have put typename , template on dependent names? dependent names anyway? have following code:

template <typename t, typename tail> // tail unionnode too. struct unionnode : public tail {     // ...     template<typename u> struct inunion {         // q: add typename/template here?         typedef tail::inunion<u> dummy;      };     template< > struct inunion<t> {     }; }; template <typename t> // last node tn. struct unionnode<t, void> {     // ...     template<typename u> struct inunion {         char fail[ -2 + (sizeof(u)%2) ]; // 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 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 whether names types or not. following example 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 program 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 data member multiplied or equally 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 copy template's text internal buffer, , when instantiation needed, parse template , possibly detect errors in definition. instead of bothering template's users (poor colleagues!) errors made template's author, other implementations choose 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 answer 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 construct - example 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, expression following 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 following innocent-looking example:

boost::function< int() > f; 

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

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

that's valid expression! uses less-than operator compare boost::function against 0 (int()), , uses greater-than operator compare 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 beginning 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>(); // call function template 

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

this->template f<int>(); // 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 use 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 precisely rules whether construct 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 expression 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 least 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 committee has started how fix 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 therefore "dependent names". name can take different forms - standard says:

a name use 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. last form template-name <argument list>. these names, , conventional use in standard, name can include qualifiers namespace or class name should looked in.

a value dependent expression 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 example f((t)0), f dependent name. in standard, specified @ (14.6.2/1).

additional notes , examples

in enough 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 last part of name. can appear in middle before class name that's used scope, in following example

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

in cases, keywords forbidden, detailed below

  • on name of dependent base 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 use template after last ::, , c++ committee 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  }; 

Comments

Popular posts from this blog

commonjs - How to write a typescript definition file for a node module that exports a function? -

openid - Okta: Failed to get authorization code through API call -

ios - Change Storyboard View using Seague -