implicit type template warning

J

Johan

Hi

Can somebody explain to me why I get this warning message and how I
can solve this warning message.

Thanks a lot

Johan

In member function `void
Callback1<Par>::search()':
b.cpp:44: warning: `typename std::vector<Callback<Par>,
std::allocator<Callback<Par> > >::iterator' is implicitly a
typename
b.cpp:44: warning: implicit typename is deprecated, please see the
documentation for details


template <class Par>
class Callback
{
public :
Callback(const Par& par) : par(par)
{
}
~Callback()
{
}

void show()
{
cout << par << endl;
}

private :
Par par;
};


template <class Par>
class Callback1 : public Callback<Par>
{
public :
typedef Callback< Par > CallbackPar;

Callback1(const Par& par) : Callback<Par>(par)
{
v.push_back(par);
}
~Callback1()
{
}

void search()
{
vector< Callback< Par > >::iterator i;
}

private :
vector< Callback< Par > > v;
};

b.cpp: In member function `void Callback1<Par>::search()':
b.cpp:44: warning: `typename std::vector<Callback<Par>,
std::allocator<Callback<Par> > >::iterator' is implicitly a
typename
b.cpp:44: warning: implicit typename is deprecated, please see the
documentation for details
 
M

msalters

Johan said:
Hi

Can somebody explain to me why I get this warning message and how I
can solve this warning message.
In member function `void
Callback1<Par>::search()':
b.cpp:44: warning: `typename std::vector<Callback<Par>,
std::allocator<Callback<Par> > >::iterator' is implicitly a
typename
b.cpp:44: warning: implicit typename is deprecated, please see the
documentation for details ....
template <class Par>
class Callback1 : public Callback<Par> {
void search() {
vector< Callback< Par > >::iterator i;

Sure. What kind of name is iterator, a template, a variable, or a type
(enum/typedef/nested class)? The compiler will know this only when it
knows what Par is, but when the template is compiled this isn't yet
known. Par will be provided later during instantiation.

The warning tells you that the compiler guessed, and it guessed
correctly. iterator is a typename. To prevent the warning, be
explicit and put the typename in yourself.
BTW, the warning said "RTFM", didn't it include this?
Regards,
Michiel Salters
 
A

Alex Vinokur

msalters said:
Sure. What kind of name is iterator, a template, a variable, or a type
(enum/typedef/nested class)? The compiler will know this only when it
knows what Par is, but when the template is compiled this isn't yet
known. Par will be provided later during instantiation.

The warning tells you that the compiler guessed, and it guessed
correctly. iterator is a typename. To prevent the warning, be
explicit and put the typename in yourself.

So,
typename vector< Callback< Par > >::iterator i;

Can something else be instead of 'typename'?

[snip]
 
D

Dietmar Kuehl

Alex said:
So,
typename vector< Callback< Par > >::iterator i;

Can something else be instead of 'typename'?

If you don't include 'typename' the compiler has to assume that it
is a value. For standard classes this may seem to be unreasable
because you have a hard time to get something else than a type
without violating some other rule but the same rule applies here
as to user defined types. For these it is pretty easy to have a
value or a type in a context and the compiler could, without the
typename, only detect the correct meaning at instantiation type.
 
A

Alex Vinokur

Dietmar Kuehl said:
If you don't include 'typename' the compiler has to assume that it
is a value.
For standard classes this may seem to be unreasable
because you have a hard time to get something else than a type
without violating some other rule but the same rule applies here
as to user defined types. For these it is pretty easy to have a
value or a type in a context and the compiler could, without the
typename, only detect the correct meaning at instantiation type.
[snip]

------ foo.cpp ------
#include <vector>
using namespace std;

template <typename T>
struct Foo
{
vector<int>::iterator iter1;
typename vector<T>::iterator iter2;
};

int main()
{
Foo<double> f;
return 0;
}
 
D

Dietmar Kuehl

Alex said:
template <typename T>
struct Foo
{
vector<int>::iterator iter1;
typename vector<T>::iterator iter2;
};

int main()
{
Foo<double> f;
return 0;
}

You mean, I failed to mention that 'typename' is only necessary
if it applies to a dependent name? (and currently prohbited if
not necessary; it is discussed to change the latter rule) Fair
enough: both 'iter1' and 'iter2' are type names because 'iter1'
does not depend on a template parameter and it is guaranteed to
the compiler that 'iter2' is indeed a type name.
 
V

Victor Bazarov

Dietmar said:
You mean, I failed to mention that 'typename' is only necessary
if it applies to a dependent name? (and currently prohbited if
not necessary; it is discussed to change the latter rule) Fair
enough: both 'iter1' and 'iter2' are type names because 'iter1'
does not depend on a template parameter and it is guaranteed to
the compiler that 'iter2' is indeed a type name.

Uh... I somehow thought that 'iter1' and 'iter2' are member names.

V
 
A

Alex Vinokur

Victor Bazarov said:
Uh... I somehow thought that 'iter1' and 'iter2' are member names.

V

It seems that _iterators_ in 'vector<int>::iterator' and 'typename vector<T>::iterator' are type names (?).
 
V

Victor Bazarov

Alex said:
It seems that _iterators_ in 'vector<int>::iterator' and 'typename
vector<T>::iterator' are type names (?).

Yes, they are. And it doesn't just seem so, it _is_ so. I was simply
surprised by the use of <<'iter1'>> and <<'iter2'>> in Dietmar's reply.

V
 
A

Alex Vinokur

Victor Bazarov said:
Yes, they are. And it doesn't just seem so, it _is_ so. I was simply
surprised by the use of <<'iter1'>> and <<'iter2'>> in Dietmar's reply.

V


Here are a sample connected to the issue.

------ file.cpp ------
struct Foo
{
struct Bar {};
static void foo (int) {}
static int data;
};
int Foo::data(0);

template <typename T>
struct Blah
{
Foo::Bar b1; // 'Bar' is explicit type name, b1 is value
Foo::Bar (b2); // 'Bar' is explicit type name, b2 is value

// T::Bar b3; // 'Bar' is implicit type name
// T::Bar (b4); // 'Bar' is implicit type name

typename T::Bar b3; // Now 'Bar' is explicit type name, b3 is value
typename T::Bar (b4); // Now 'Bar' is explicit type name, b4 is value

void blah1 () { int x(0); T::foo(x); } // 'foo' is explicit function name
void blah2 () { T::data; } // 'data' is explicit value name

// ----------------------
void blah3 (Foo::Bar, typename T::Bar, void (*)(int), int) {}
// 'Bar' in Foo::Bar is explicit type name
// 'Bar' in T::Bar is now explicit type name
// ----------------------
};

int main()
{
Foo::Bar bar;

Blah<Foo> blah;

// ---------
blah.blah1();

blah.blah2();
// ---------

// ----------------------------------------
blah.blah3 (bar, bar, Foo::foo, Foo::data);
// 'foo' is explicit function name
// 'data' is explicit value name
// ----------------------------------------

return 0;
}
 
D

Dietmar Kuehl

Victor said:
Uh... I somehow thought that 'iter1' and 'iter2' are member names.

Stupid me: spreading more confusion than knowledge! Of course, both
are member names. I apparently got confused by the question...

The reason why 'typename' is required when using dependent names is
that there are contexts where an ambiguity between a type and a
variable can occur. The typical example is something like this:

int foo = 0;
template <typename T> struct bar { static int const type = 0; };
template <> struct bar<int> { typedef int type; } // stupid...

template <typename T> void f() {
bar<int>::type* f; // pointer declaration
bar<T>::type * foo; // useless multiplication
}

The second statement in 'f()'s body is considered to be a
multiplication, even when instantiated with type 'int' in which
case it would cause a compiler error: 'bar<T>::type' depends on a
template parameter and is thus a dependent name. Dependend names
are considered to be objects unless qualified by 'typename'.
Non-dependent names, like 'bar<int>::type' can be immediately
deduced, i.e. there is no need to wait until instantiation to
find out that it is actually a type.
 
A

Alex Vinokur

Dietmar Kuehl said:
Stupid me: spreading more confusion than knowledge! Of course, both
are member names. I apparently got confused by the question...

Sorry, my question was incorrectly formulated.
The reason why 'typename' is required when using dependent names is
that there are contexts where an ambiguity between a type and a
variable can occur. The typical example is something like this:

int foo = 0;
template <typename T> struct bar { static int const type = 0; };
template <> struct bar<int> { typedef int type; } // stupid...

template <typename T> void f() {
bar<int>::type* f; // pointer declaration
bar<T>::type * foo; // useless multiplication
}

The second statement in 'f()'s body is considered to be a
multiplication, even when instantiated with type 'int' in which
case it would cause a compiler error: 'bar<T>::type' depends on a
template parameter and is thus a dependent name. Dependend names
are considered to be objects unless qualified by 'typename'.
Non-dependent names, like 'bar<int>::type' can be immediately
deduced, i.e. there is no need to wait until instantiation to
find out that it is actually a type.
[snip]

g++ 3.3 accepts a code below.
g++ 3.4 rejects it.

------ file.cpp ------
int foo = 0;

template <typename T> struct bar { static int const type = 0; };
template <> struct bar<int> { typedef int type; };

template <typename T> void f()
{
bar<int>::type* ptr; // pointer declaration
bar<T>::type * foo; // useless multiplication // Line#9
typename bar<T>::type * bar; // now explicit type name
}

int main()
{
int i = bar<double>::type * foo;

f<int>(); // Line#17

return 0;
}
----------------------


--- Compilation ---

// gpp.exe (GCC) 3.4.1

$ gpp file.cpp

file.cpp: In function `void f() [with T = int]':
file.cpp:17: instantiated from here
file.cpp:9: error: dependent-name `bar<T>::type' is parsed as a non-type, but instantiation yields a type
file.cpp:9: note: say `typename bar<T>::type' if a type is meant
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Similar Threads


Members online

No members online now.

Forum statistics

Threads
474,164
Messages
2,570,898
Members
47,439
Latest member
shasuze

Latest Threads

Top