|
Hello everyone,
According to standard, the code should not compile.
http://gcc.gnu.org/onlinedocs/gcc/Name-lookup.html
template <typename T> struct Base {
int i;
};
template <typename T> struct Derived : public Base<T> {
int get_i() { return i; }
};
But it can compile without any issues in Visual Studio 2008, without any warnings and even if I select disable language extensions to yes.
Any comments? What is wrong?
thanks in advance,
George
|
|
|
|
|
George_George wrote: According to standard, the code should not compile.
What do you mean with standard?
As far as I can tell the snippit looks fine. And i think that the manual is wrong on this one.
They state: In get_i(), i is not used in a dependent context according to me this is wrong since i is without any doubt the Base<T>::i which is known.
This is indeed a strange situation.
codito ergo sum
|
|
|
|
|
Thanks BadKarma,
Seems like Visual Studio is wrong. Please look at section 35.19 of,
http://www.parashift.com/c++-faq-lite/templates.html#faq-35.19[^]
1.
I think this line of statement matters, agree?
--------------------
the compiler does not look in dependent base classes (like B<T>) when looking up nondependent names (like f).
--------------------
2.
What disadvantage do we have if the code can compile?
regards,
George
|
|
|
|
|
I think current versions of VC++ treat this issue in the manner treating non-template name hiding stuff. Such as:
int a = 3;
for(int i = 0, a = 0; i < 2; i++) {
printf("a = %d \n", a);
}
printf("a = %d \n", a);
Result:
a = 0
a = 3
Maxwell Chen
|
|
|
|
|
Hi Maxwell,
1. I think Visual Studio 2008 provides correct result in the sample you provided. Are there anything wrong?
2. Does your sample have anything related to my question?
regards,
George
|
|
|
|
|
George_George wrote: 1. I think Visual Studio 2008 provides correct result in the sample you provided. Are there anything wrong?
2. Does your sample have anything related to my question?
1. I haven't found where in the ISO C++:2003 states how this issue should be working.
But, remember?! You posted Stroustrup's words in previous thread.
And that quote matches GCC document's statement.
2. Something about name resolution ...
Maxwell Chen
|
|
|
|
|
|
George_George wrote: Seems like Visual Studio is wrong. Please look at section 35.19 of,
http://www.parashift.com/c++-faq-lite/templates.html#faq-35.19[^]
1.I think this line of statement matters, agree?
--------------------
the compiler does not look in dependent base classes (like B<t> when looking up nondependent names (like f).
--------------------
This is correct Visual Studio compiles the non-valid code without any troubles
George_George wrote: 2. What disadvantage do we have if the code can compile?
Thats a hard one since Visual Studio compiles and provides the correct solution. Even when there are global variables or function is correctly understand what the programmer wants and does a check the base class first.
This brings us too two other questions one might ask.
1. Can one write code which breaks this rule? Meaning, can on write code that explicit calls the global function instead of the base function?
2. If this is not possible, why does the rule: the compiler does not look in dependent base classes (like B<t> when looking up nondependent names (like f). exist? Is it because older compilers where not smart enough to clear this up?
codito ergo sum
|
|
|
|
|
The intention Stroustrup and the ISO C++ team defined this seems because they hoped to avoid the "nasty macro-like behaviours" (see George's previous thread).
Maxwell Chen
|
|
|
|
|
Hi Maxwell,
I understand what means "nasty macro-like behaviours", but I do not think "nasty macro-like behaviours" is similar to my sample in original question?
regards,
George
|
|
|
|
|
George_George wrote: I understand what means "nasty macro-like behaviours", but I do not think "nasty macro-like behaviours" is similar to my sample in original question?
Your sample in the original question in this thread originated from your previous thread quoting Stroustrup's words. You forgot?!
Maxwell Chen
|
|
|
|
|
Don't push me doing copy-and-paste!!
Maxwell Chen
|
|
|
|
|
What do you mean, Maxwell?
regards,
George
|
|
|
|
|
George_George wrote: What do you mean, Maxwell?
(I am home, so I can copy-and-paste now! )
In the beginning, you quoted Stroustrup's words.
Not can an unqualified name used in a template
ever be bound to a local name. Finally, even if a template
is first used within a class, unqualified names used in the template
will not be bound to members of that class.
Ignoring lcoal names is essential to prevent a lot of
nasty macro-like behavior.
section C.18.3.3 Point of Instantiation Binding
So I gave you that GCC document[^], which introduced this code sample.
Doesn't the code match what Stroustrup said?!
template <typename T>
struct Base {
int i;
};
template <typename T>
struct Derived : public Base<T> {
int get_i() { return i; }
};
Maxwell Chen
|
|
|
|
|
Thanks Maxwell,
I am interested about your points,
--------------------
Even if a template is first used within a class, unqualified names used in the will not be bound to members of that class.
--------------------
To make discussion clear, could you let me know,
1. what is a template do you refer to in the sample?
2. what is the class (within a class) do you refer to in the sample?
3. what is the unqualified names do you refer to in the sample?
4. what is the "members of that class" do you refere to in the sample?
regards,
George
|
|
|
|
|
George_George wrote: 1. what is a template do you refer to in the sample?
2. what is the class (within a class) do you refer to in the sample?
3. what is the unqualified names do you refer to in the sample?
4. what is the "members of that class" do you refere to in the sample?
1. You saw the keyword template .
2. A struct is a class with members being public by default.
3. That i .
4. That i is the member of the struct (class ).
Maxwell Chen
|
|
|
|
|
Thanks Maxwell,
I am confused about your points 1 and 2.
I can not believe when Bjarne said "Even if a template is first used within a class", he means even if a template keyword? is first used within a class? It should be some specific template, right?
Should it mean even if template Base<t> first used within a class Derived<t>?
Maxwell Chen wrote: 1. You saw the keyword template.
2. A struct is a class with members being public by default.
regards,
George
|
|
|
|
|
George_George wrote: I can not believe when Bjarne said "Even if a template is first used within a class", he means even if a template keyword? is first used within a class? It should be some specific template, right?
I review the section C.13.8.3 again. I think that the GCC sample fits the first sentence.
Not can an unqualified name used in a template
ever be bound to a local name.
And you were challenging
a template is first used within a class
v.s.
template Base first used within a class Derived ...
Stroustrup's sample code on page 863 in section C.13.8.3 explains the 2nd sentence.
Finally, even if a template is first used within a class,
unqualified names used in the template will
not be bound to members of that class.
template<classT>
void sort(vector<T>& v)
{
sort(v.begin(), v.end());
}
class Container{
vector<int> v;
public:
void sort()
{
sort(v);
}
};
Maxwell Chen
|
|
|
|
|
Hi Maxwell,
For your quoted comments below,
Maxwell Chen wrote: Not can an unqualified name used in a template ever be bound to a local name.
Do you mean this sample from gcc document?
http://gcc.gnu.org/onlinedocs/gcc/Name-lookup.html[^]
template <typename T> struct Base {
int f();
};
template <typename T> struct Derived : Base<T> {
int g() { return f(); };
};
In the statement, unqualified name you mean f in class Derived or? Bound to a local name? What is the local name? I am confused.
2.
For your below quoted comments,
Maxwell Chen wrote: Finally, even if a template is first used within a class, unqualified names used in the template will not be bound to members of that class.
Do you mean you quoted sample (sort function and Container class) matches the above statement?
regards,
George
|
|
|
|
|
Yes, but anything in this question is similar to "nasty macro-like behaviours"? Maxwell?
regards,
George
|
|
|
|
|
Thanks BadKarma,
1.
BadKarma wrote: Even when there are global variables or function is correctly understand what the programmer wants and does a check the base class first.
I do not quite understand what do you mean this? Could you provide more information or some pseudo code please?
2.
BadKarma wrote: 1. Can one write code which breaks this rule? Meaning, can on write code that explicit calls the global function instead of the base function?
Sure, we can. Here is the code to prove.
#include <iostream>
using namespace std;
static int i = 100;
template <typename T> struct Base {
public:
Base (int _i): i (_i)
{
}
int i;
};
template <typename T> struct Derived : public Base<T> {
public:
Derived (int _i) : Base<T> (_i)
{
}
int get_i() { return ::i; }
};
int main()
{
Derived<int> d (200);
cout << d.i << endl;
cout << d.get_i() << endl;
return 0;
}
regards,
George
|
|
|
|
|
George_George wrote: Sure, we can. Here is the code to prove.
#include <iostream>
using namespace std;
static int i = 100;
template <typename t=""> struct Base {
public:
Base (int _i): i (_i)
{
}
int i;
};
template <typename t=""> struct Derived : public Base<t> {
public:
Derived (int _i) : Base<t> (_i)
{
}
int get_i() { return ::i; }
};
int main()
{
Derived<int> d (200);
cout << d.i << endl; // output 200
cout << d.get_i() << endl; // output 100
return 0;
}
I believe this is a correct output since you explicit wanted to use the global i:
int get_i() { return ::i; }
codito ergo sum
|
|
|
|
|
Thanks BadKarma,
What do you mean this before?
"Even when there are global variables or function is correctly understand what the programmer wants and does a check the base class first."
regards,
George
|
|
|
|
|
George_George wrote: What do you mean this before?
"Even when there are global variables or function is correctly understand what the programmer wants and does a check the base class first."
By this I mean the following: If you don't use the :: before the i in your code sample, the VC compilter correctly choses the i defined in the base class.
If you don't have an i in your base class it correctly choses the globally defined i. If there is neither an i defined in the base class or on global scope it results in an error. So in all cases the VC compiler chooses the solution that the programmer wanted.
codito ergo sum
|
|
|
|
|
Thanks BadKarma,
BadKarma wrote: the VC compilter correctly choses the i defined in the base class.
According to our discussion, this is not standard compatible behavior, agree? A compile error should be reported in this case if no global i is defined.
regards,
George
|
|
|
|