Which compiler is correct for the following overload / specialization behavior?

Consider the following code:

#include <stdio.h> namespace Foo { template <typename T> void foo(T *, int) { puts("T"); } template <typename T> struct foo_fun { static void fun() { foo((T *)0, 0); }; }; } namespace Foo { void foo(int *, int) { puts("int"); } } using namespace Foo; int main() { foo_fun<int> fun; fun.fun(); } 

What is the expected result? "T" or int?

One compiler (gcc 4.0.1 from Apple Xcode 3.1.2) outputs "int", the other two compilers (gcc 4.1.2 and 4.1.3) output "T".

If I go to the declaration / definition of foo (int *, int) before the version of foo (T *, int), everyone outputs "int". Is the overload / specialization order in this case defined by the current standard?

+4
source share
2 answers

The second void foo(... is an overload (not a specialization) that is not visible in the definition of foo_fun::fun , so it will not be found in the context of the template definition. Since T* is a dependent type, the resolution of foo in the expression foo((T*)0, 0) will be delayed until the time of creating the template and the context of the instance are considered.However, the standard 14.6.4.2 says that if the function name is an unqualified identifier but not a template identifier, then for a search without ADL only functions visible at the template definition point are considered . There are no arguments to the function of the namespace foo , so the search is dependent on the arguments does not occur, so called template version of foo , and not overload without template.

Many thanks to the light bulb for correcting this answer.

If you made this specialization, as shown below, when specializations are selected during template creation, specialization can be called up until the corresponding specialization is visible at the moment when the function template is first created for int .

 namespace Foo { template<> void foo<int>(int *, int) { puts("int"); } } 

Chapter 14 of the current standard, but not very readable :)

Edit: if I needed to choose the most appropriate part of the standard, it would probably be 14.6 [temp.res] para 9. (Slightly abbreviated). If the name does not depend on the template parameter, the declaration for this name should be in scope at the point where the name is displayed in the template definition; the name is tied to the ad found at this point, and this tidy is not affected by the ads that are visible at the time the instance was created.

Edit, edit: But you also need to take into account 14.6.4.2 [temp.dep.candidate]. It is very difficult and dangerous to try to reference the standard because of all the interdependencies, this answer is an example.

+9
source

Typically, of the two compiler versions, the later version is more standard.

0
source

All Articles