|
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
|
|
|
|
|
This is a known issue in Visual C++. Microsoft document this non-standard behaviour here[^].
I wouldn't be surprised to find that a fair bit of ATL would need to be rewritten when this issue is fixed.
DoEvents: Generating unexpected recursion since 1991
|
|
|
|
|
|
A template is instantiated for a given set of parameters when it is first used, so it is g('c') which instantiates g<char> . The template argument is deduced from the type of the argument to the function call.
The problem here is that the standard calls for anything not dependent on the template parameters (the stuff between <> ) to be bound at the point that the template is defined, not the point that it is instantiated. Only those references that depend upon the template parameters are supposed to be deferred until the point that the template is instantiated.
In the example given at that link:
namespace N {
void f(int) { printf("f(int)\n");}
}
template <class T> void g(T) {
N::f('a');
}
namespace N {
void f(char) { printf_s("f(char)\n");}
}
int main() {
g('c');
} The standard says that when the definition of g(T) is encountered, anything not explicitly dependent on the argument T should be bound. At this point we have encountered the declaration of N::f(int) but not yet the declaration of N::f(char) . Because char is implicitly convertable to int, a standard-compliant compiler would bind to N::f(int) . If the declaration of N::f(int) wasn't there, an error would occur.
Visual C++ at present does not do this first step of binding and defers all name resolution to the point of instantiation. This is when the call to g is encountered. At this point the compiler has seen both overloads of N::f so it binds to N::f(char) as that is the best match.
Say instead the declaration of g were:
template <class T> void g(T t) {
N::f(t);
} Now the call to N::f is dependent on the type of the parameter t which is the template argument T . Here, the compiler cannot bind the call to N::f when it encounters the template definition because it does not know what T is. It has to defer it until the template is instantiated. When the call to g('c') is encountered, it knows that the type parameter T is char , so it generates a call to N::f(char) . This is true of both Visual C++ and a standards-compliant compiler.
In your original example, the use of the variable i is not explicitly dependent on the template argument T so it is assumed not to be dependent. A standard compiler tries to bind to a global i and generates an error if one is not found. Visual C++ will wait until the template is instantiated and bind to the base class's i member as that is the closest i in scope at the point of instantiation. To make the standards compiler wait until the point of instantiation, you have to make the expression depend on the base class: if i is expected to be an instance member, use this->i , otherwise if it's a static member use Base<T>::i .
DoEvents: Generating unexpected recursion since 1991
|
|
|
|
|
Thanks Mike,
Your reply is cool and makes me clear about more things. I stuied my original question again, and modify the sample to make it more clear to debug. I have tried to use your analysis above to explain why if we comment the cout d.get_i() statement, there will be compile error, but if we comment it out, there will not be compile error.
Any ideas?
Compile errors are,
1>------ Build started: Project: test_template4, Configuration: Debug Win32 ------
1>Compiling...
1>main.cpp
1>d:\visual studio 2008\projects\test_template4\test_template4\main.cpp(20) : error C2065: 'i' : undeclared identifier
1> d:\visual studio 2008\projects\test_template4\test_template4\main.cpp(20) : while compiling class template member function 'int Derived<T>::get_i(void)'
1> with
1> [
1> T=int
1> ]
1> d:\visual studio 2008\projects\test_template4\test_template4\main.cpp(26) : see reference to class template instantiation 'Derived<T>' being compiled
1> with
1> [
1> T=int
1> ]
#include <iostream>
using namespace std;
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.get_i() << endl;
return 0;
}
regards,
George
|
|
|
|
|
I m working on Audio and video related software.
i want to attach bar visulizer for audio file(just Like window media player's Bar visulizer).
but i dont want to use ActiveX cotrol.
Please anyone can help me for this.
Thanks in advance.
|
|
|
|
|
Hi Everybody,
I m developing a Task manager like application. I m able to enumerate the process list. But i m not able to get the active window list. That is the content of the first tab in the task Manager. Can anybody help me please??
|
|
|
|
|
EnumWindows() and GetWindowThreadProcessId() to get the lop level application window and there by its process id;
|
|
|
|