------- Comment #6 from martin dot audet at imi dot cnrc-nrc dot gc dot ca 2007-05-30 21:02 ------- I'm the original submiter of this bug and I'am not sure now if it's a bug in g++ template instantiation mechanism (e.g. problem with the two phase name lookup) or if the code example itself is standard compliant.
We need a couple of C++ experts to look at this "problem" carefully to decide if the two phases template name binding process is incorrect as I reported or if the code sample is incorrect (if that's the case maybe g++ needs to emit a warning at least) or if g++ current behavior is correct. I'm now expressing doubts since I submited a similar issue with Intel C/C++ compiler using the following code sample (similar but slightly longer): #include <iostream> // "f" in g<T>(T) should bind to this function even if "f" // is overloaded later with a more "natural" version. void f(double) { std::cout << "Function f(double)" << std::endl; } template<class T> void g(T a) { f(123); // "f" is not a dependent name. Binding occurs at definition (e.g. here). h(a); // "h" is a dependent name. Binding will occurs at instantiation point. } // "f" in g<T>(T) should not bind to this function even if it is more "natural". void f(int) { std::cout << "Function f(int)" << std::endl; } // "h" in g<int>() should be bound to this function even // if "h" is overloded later with a more "natural" version. void h(double) { std::cout << "Function h(double)" << std::endl; } // Instantiation point for g<int>(). void i(void) { extern void h(int); // Should not influence the choice of the "h" function. // because it is out of scope at instantiation point. // Note: the problem with h instantiation occur even // if this declaration is commented out. g(234); // g<int>(234) is called. } // "h" in g<int>() should be not be bound to this version of // "h" function even if it is more "natural". This is because // its declaration occurs after instatiation point. void h(int) { std::cout << "Function h(int)" << std::endl; } int main(void) { // Should print: // "Function f(double)". // "Function h(double)". i(); return 0; } This code was taken from an example in a IBM Developer Works article where the author explained that the two phases template name binding process (the comments are added by me). The article stated that the correct result was to print: Function f(double) Function h(double) I remember at that time trying it on one AIX machine witch xlC C++ compiler and it effectively printed that result. I also tried it on a few other compilers/systems and I remember having the four possible outcomes (f(double)/f(int), h(double)/h(int)). Recent g++ and icpc (Intel C++ compiler v9.1) versions now prints: Function f(double) Function h(int) Since I was convinced that this was a bad result I submited this bug report for g++ and a bug report for Intel compiler. The answer I finally got from Intel compiler team (before closing the case) suggest that this code sample isn't standard compliant and therefore there wasn't a template instantiation problem. Here is the answer I got: Intel answer BEGIN Hi Martin, The development team has had another look at this and have determined that the test case is not standard conforming. """ The compiler is right to issue the error. There are two rules for the Dependent name resolution in C++ strandard. 14.6.4 Dependent name resolution [temp.dep.res] 1 In resolving dependent names, names from the following sources are considered: - Declarations that are visible at the point of definition of the template. - Declarations from namespaces associated with the types of the function arguments both from the instantiation context (14.6.4.1) and from the definition context. The first rule, said we need to have a declaration of "h" before definition of the template. But in this test case we don't have. For the second rule, the namespaces for type "int" is empty according 3.4.2 as following. So this test case does not match this rule too. The test case is not standard conforming. The compiler is right on it. 3.4.2. For each argument type T in the function call, there is a set of zero or more associated namespaces and a set of zero or more associated classes to be considered. The sets of namespaces and classes is determined entirely by the types of the function arguments (and the namespace of any template template argument). Typedef names and usingdeclarations used to specify the types do not contribute to this set. The sets of namespaces and classes are determined in the following way: - If T is a fundamental type, its associated sets of namespaces and classes are both empty. """ Thank you. -- Intel answer END So with this answer I don't know what to think, is the sample program standard compliant ? Is there a warning missing ? Is the current name binding process for template standard compliant ? We need C++ experts to look at this problem. -- http://gcc.gnu.org/bugzilla/show_bug.cgi?id=23885