问题
I test the code in the c++ standard ISO/IEC 14882-03 14.6.1/9 on Xcode 4.1 and Visual Studio 2008. The outputs of the two compiler are both different from the expected result of the standard.
The code is pasted below.
#include <stdio.h>
#include <iostream>
using namespace std;
void f(char);
template <class T > void g(T t)
{
f(1);
f(T(1));
f(t);
}
void f(int);
void h()
{
g(2);
g('a');
}
void f(int)
{
cout << "f int" << endl;
}
void f(char)
{
cout << "f char" << endl;
}
int main() {
h();
return 0;
}
As the description of the standard. The expected output should be
f char
f int
f int
f char
f char
f char
Build and run the code on Xcode 4.1. The output is as below. In the build settings, I tried to change the "Compiler for C/C++/Object-C" to be Apple LLVM Compiler 2.1, Gcc 4.2 and LLVM GCC 4.2. The outputs are the same.
f char
f char
f char
f char
f char
f char
Build and run the code on Microsoft Visual Studio 2008. The output is as below.
f int
f int
f int
f int
f char
f char
The description (14.6.1/9) of the standard is pasted below.
If a name does not depend on a template-parameter (as defined in 14.6.2), a declaration (or set of declara- tions) for that name shall be in scope at the point where the name appears in the template definition; the name is bound to the declaration (or declarations) found at that point and this binding is not affected by declarations that are visible at the point of instantiation. [Example:
void f(char);
template<class T> void g(T t)
{
f(1); // f(char)
f(T(1)); // dependent
f(t); // dependent
dd++; // not dependent
}
void f(int);
double dd;
void h()
{
// error: declaration for dd not found
g(2); // will cause one call of f(char) followed // by two calls of f(int)
g(’a’); // will cause three calls of f(char)
—end example]
The code is well-formed to the compilers, but the outputs are different. It would be very dangerous to port this code to different platforms.
Does somebody have the background why these compilers don't follow the standard?
Edit on 10/11/2011
Per http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#197, the example in the standard is wrong. I test the code below on Clang and Gcc.
#include <stdio.h>
#include <iostream>
using namespace std;
void f(char);
template <class T > void g(T t)
{
f(1);
f(T(1));
f(t);
}
enum E{ e };
void f(E );
void h()
{
g(e);
g('a');
}
void f(E )
{
cout << "f E" << endl;
}
void f(char)
{
cout << "f char" << endl;
}
int main() {
h();
return 0;
}
The output as expected.
f char
f E
f E
f char
f char
f char
Thanks,
Jeffrey
回答1:
As noted in the first example, this is an instance of two-phase name lookup, which both GCC and Clang implement but MSVC does not. And in this case, both GCC and Clang are correct: it's actually the standard that is wrong, as noted in C++ core defect report #197. The C++11 standard contains a different example.
This is one of the most common problems we see when porting code to Clang from either MSVC (which never implemented two-phase name lookup) or from GCC (which didn't implement two-phase name lookup uniformly until recently).
回答2:
What you're running into is the fact that Visual Studio does not implement two-phase lookup. They only look up the actual name when you instantiate the template.
And Microsoft has pretty much decided at this point that they're not interested in supporting two-phase lookup.
回答3:
I don't know what to tell you except that I would agree with you that this is incorrect behavior.
I think what's probably happening is that in the case of MSVC, the compiler is optimizing away an extra pass at the cost of ending up with the knowledge of a later-defined function that should not be use in the case of non-template calls. I must confess, I don't get how GCC/LLVM would end up with the results that they do, as the results are what you would expect as the exception and not the rule.
I guess I'd file it as a bug on http://bugreport.apple.com/ and http://connect.microsoft.com/ and see what they say?
来源:https://stackoverflow.com/questions/7630806/the-actual-result-of-name-resolution-in-the-class-template-is-different-from-the