tags:

views:

55

answers:

2

While experimenting a bit with C++ templates I managed to produce this simple code, for which the output is different, than I expected according to my understanding of C++ rules.

void bar(double d)
{
    std::cout << "bar(double) function called" << std::endl;
}

template <typename T> void foo(T t)
{
    bar(3);
}

void bar(int i)
{
    std::cout << "bar(int) function called" << std::endl;
}

int main()
{
    foo(3);
    return 0;
}

When I compile this code in VC++2008 Express, function bar(int) gets called. That would be the behaviour, I would expect if bar(3);in the template body was dependent on the template parameter. But it's not. The rule I found here says "The C++ standard prescribes that all names that are not dependent on template parameters are bound to their present definitions when parsing a template function or class". Am I wrong, that "present definition" of bar when parsing the template function foo is the definition of void bar(double d);? Why it's not the case if I am wrong. There are no forward declarations of bar in this compilation unit.

+3  A: 

It is indeed a bug in the compiler. The problem was known to exist in VS2005 and before (I use a Blogspot blog as a notebook for cases like this, see 1.3 here). Apparently it is present in VS2008 as well.

You can test it with the following simple code

int bar(double d) { return 0; }

template <typename T> void foo(T t) {
  int i = bar(3);
}

void bar(int i);

int main() {
  foo(3);
}

This code is well-formed (you can compile it with Comeau Online compiler), but I bet that VS will choke on it because VS implements the two-phase lookup incorrectly in this case.

AndreyT
Yup, VS (well at least my Express version, but I think it's the same compiler in others) claims there are errors in the code. Thank You.
Maciej Hehl
this error still shows up on visual studio 2010.
smerlin
+2  A: 

AndreyT is correct. In fact, your code is virtually identical to an example from the standard (§14.6.3/1):

void g(double);
void h();

template<class T> class Z {
public:
    void f() {
        g(1);    //calls g(double)
        h++;     //ill-formed: cannot increment function;
                 // this could be diagnosed either here or
                 // at the point of instantiation
    }
};

void g(int);     // not in scope at the point of the template
                 // definition, not considered for the call g(1)
Jerry Coffin