Quote:
Code:
class DB
{
public:
static int i;
}
... OR ...
Code:
class DB
{
public:
typedef int i;
}
|
(corrected slightly)
DB::i will give you access to whatever ' i ' is. However, the same syntax is used to access both, DB::i does not tell me if i is a value or a type, the first or the second case above.
In the first case ' i ' is a
value, a class scope integer that can be accessed through the use of the scope resolution operator ::
You can write:
DB::i = 100;
With the second example, ' i ' is a
type. You can write code that will declare an integer like this:
DB::i value = 100;
However, sometimes this second case presents a problem to the compiler. In theory, we humans can tell the difference quite easily, but not quite so for the compiler which may not have access to the whole template definition and cannot jump about the code like humans can and needs to produce nice error messages that are vaguely readable in a timeframe considerable shorter than a week.
So the second example may require a prefix of typename:
typename DB::i value = 100;
Hence, typename gives the difference between a value and a type.
When do you need to do something like this, though?
Answer : In a template.
Consider writing a function to print the maximum value of any container.
We want to get a temporary value of whatever type is contained in that container.
Luckily, in the standard library, the containers provide us with a typedef called value_type.
More than that, they also provide us with a typedef that gives us 'something' to iterate over the container with, called an iterator.
We can now write a function like this:
Code:
template<typename container_t>
void
show_me_the_biggest(const container_t& c)
{
typename container_t::const_iterator i = c.begin();
typename container_t::value_type max = *(i++);
for (; i != c.end(); ++i)
if (*i > max) max = *i;
cout << "Maximum is : " << max << endl;
}
We have to tell the compiler that 'iterator' and 'value_type' are like the SECOND case in the quote above, i.e.
types.
Although, just to complicate matters (because life is never simple) you do not need the typename keyword if you are not in a template, if you were to write the same code in a non-generic form.
As a rule of thumb, if you can read the code on your screen and determine the entire type of the template (i.e. what all the parameters are) then you don't need typename.
The opposite example is a template function for any types with a common static value defined (but none spring to mind at the moment!)