C++ template

  • Thread starter Unkown to Xnntp
  • Start date
U

Unkown to Xnntp

Hello,

The following code works (it compiles ok with "g++ test.c"):

++++++++++++++++++++++++++++++++++++++++
template <class Value> class Test1 {
public:
int a;
};

class Test2 : public Test1<int> {
public:
void f() {
a = 2;
}
};
++++++++++++++++++++++++++++++++++++++++


However, the following code does not compile:
++++++++++++++++++++++++++++++++++++++++
template <class Value> class Test1 {
public:
int a;
};

template <class Value> class Test2 : public Test1<Value> {
public:
void f() {
a = 2;
}
};
++++++++++++++++++++++++++++++++++++++++
the compiler (g++-4.0.1) says:
test.c: error: a was not declared in this scope


What is the problem?
ps: the code above does not do anything interesting.
It is just here to illustrate the problem that I currently find while compiling
my other real program.


Many thanks,
DAvid
 
K

kwikius

Unkown said:
<...>

template <class Value> class Test2 : public Test1<Value> {
public:
void f() {
Test1<Value>:: a = 2;
}
};

Think its something like the above. Because you inherit from template
you need to be explicit about base . Something to do with
specialisations etc where in specialisaion compiler cant assume same as
default.

Untested in gcc ( orig works OK in VC8)

regards
Andy Little
 
P

Pascal J. Bourguignon

Unkown to Xnntp said:
However, the following code does not compile:
++++++++++++++++++++++++++++++++++++++++
template <class Value> class Test1 {
public:
int a;
};
template <class Value> class Test2 : public Test1<Value> {
public:
void f() {
a = 2;
}
};
++++++++++++++++++++++++++++++++++++++++
the compiler (g++-4.0.1) says:
test.c: error: .a. was not declared in this scope

What is the problem?

With this->a=2; it works.
 
A

aman.c++

template <class Value> class Test1 {
public:
int a;

};

template <class Value> class Test2 : public Test1<Value> {
public:
void f() {
a = 2;
}};
the compiler (g++-4.0.1) says:
test.c: error: a was not declared in this scope
What is the problem
Hi,
The problem is that Test1<Value> is a dependent base class and the
variable a is a non-dependent name. Compilers that use 2 phase lookup
lookup the non-dependent names early but the dependent names can't be
resolved when parsing templates. The are resolved at instantiation (ph
2). Hence the name a is ambiguous.

To resolve this you could make the name "a" also dependent using
either of:

Test1<Value> ::a = 2;
this->a = 2;

For your case either line will work fine but there are situations when
one might be preferred over the other.

regards,
Aman Angrish
 
D

David Portabella

aman.c++ said:
Hi,
The problem is that Test1<Value> is a dependent base class and the
variable a is a non-dependent name. Compilers that use 2 phase lookup
lookup the non-dependent names early but the dependent names can't be
resolved when parsing templates. The are resolved at instantiation (ph
2). Hence the name a is ambiguous.

To resolve this you could make the name "a" also dependent using
either of:

Test1<Value> ::a = 2;
this->a = 2;

For your case either line will work fine but there are situations when
one might be preferred over the other.

regards,
Aman Angrish


One more question,

is there a difference between these two possibilities in terms of
execution time?
or, once compiled, they look exactly the same?


Best regards,
DAvid
 
J

Juha Nieminen

Unkown said:
template <class Value> class Test2 : public Test1<Value> {

Hate to nitpick about style, but newlines *are* allowed to be used in
source code for clarity.
 
J

James Kanze

The problem is that Test1<Value> is a dependent base class and
the variable a is a non-dependent name.

As written, the compiler treats it as non-dependent. The author
of the code obviously wanted it to be dependent.
Compilers that use 2 phase lookup

In other words, compilers that conform to the C++ standard.
lookup the non-dependent names early but the dependent names
can't be resolved when parsing templates. The are resolved at
instantiation (ph 2). Hence the name a is ambiguous.

Not quite. First, the name isn't ambiguous; it isn't found,
because non-dependent lookup occurs at the point where the
template is defined, not where it is instantiated, and doesn't
take dependent base classes into account. (Note that if he'd
derived from Test1<int>, there'd be no problem.)

Dependent names are more complicated, and are searched both in
the context where the template was defined, and in the context
where it was instantiated, but only using ADL in the latter
case.
To resolve this you could make the name "a" also dependent
using either of:
Test1<Value> ::a = 2;
this->a = 2;

Yes. It's a shame that one has to resource to such tricks,
however, rather than simply being able to say what one means
(e.g. by explicitly declaring which names should be dependent).
For your case either line will work fine but there are
situations when one might be preferred over the other.

I think that the "this->" is the usual solution, and so it
should be preferred as long as there are no real reasons to do
otherwise.
 
J

James Kanze

Hate to nitpick about style, but newlines *are* allowed to be
used in source code for clarity.

I agree, and the above would be three or four lines in my own
code. But I think a lot of people compress the code when
posting, on the grounds that a ten line posting is more likely
to get answers than a twenty line one.
 

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

Members online

Forum statistics

Threads
474,170
Messages
2,570,927
Members
47,469
Latest member
benny001

Latest Threads

Top