Saturday 6 April 2019

c++ - When is the "typename" keyword necessary?










consider the code below:




template
class C {
struct P {};
vector

vec;
void f();
};

template void C::f() {
typename vector

::iterator p = vec.begin();
}



Why is the "typename" keyword necessary in this example?
Are there any other cases where "typename" must be specified?


Answer



Short answer: Whenever referring to a nested name that is a dependent name, i.e. nested inside a template instance with unknown parameter.



Long answer: There are three tiers of entities in C++: values, types, and templates. All of those can have names, and the name alone doesn't tell you which tier of entity it is. Rather, the information about the nature of a name's entity must be inferred from the context.



Whenever this inference is impossible, you have to specify it:




template  struct Magic; // defined somewhere else

template struct A
{
static const int value = Magic::gnarl; // assumed "value"

typedef typename Magic::brugh my_type; // decreed "type"
// ^^^^^^^^


void foo() {
Magic::template kwpq(1, 'a', .5); // decreed "template"
// ^^^^^^^^
}
};


Here the names Magic::gnarl, Magic::brugh and Magic::kwpq had to be expliciated, because it is impossible to tell: Since Magic is a template, the very nature of the type Magic depends on T -- there may be specializations which are entirely different from the primary template, for example.



What makes Magic::gnarl a dependent name is the fact that we're inside a template definition, where T is unknown. Had we used Magic, this would be different, since the compiler knows (you promise!) the full definition of Magic.




(If you want to test this yourself, here's a sample definition of Magic that you can use. Pardon the use of constexpr in the specializaation for brevity; if you have an old compiler, feel free to change the static member constant declaration to the old-style pre-C++11 form.)



template  struct Magic
{
static const T gnarl;
typedef T & brugh;
template static void kwpq(int, char, double) { T x; }
};
template <> struct Magic

{
// note that `gnarl` is absent
static constexpr long double brugh = 0.25; // `brugh` is now a value
template static int kwpq(int a, int b) { return a + b; }
};


Usage:



int main()

{
A a;
a.foo();

return Magic::kwpq(2, 3); // no disambiguation here!
}

No comments:

Post a Comment

php - file_get_contents shows unexpected output while reading a file

I want to output an inline jpg image as a base64 encoded string, however when I do this : $contents = file_get_contents($filename); print &q...