Thread: Template name binding - instantiation point

  1. #1
    Registered User
    Join Date
    Jun 2008
    Location
    Somewhere in Europe
    Posts
    99

    Template name binding - instantiation point

    Code:
    #include <iostream>
    
    using namespace std;
    
    void f(const char*)
    {
        cout << "f(const char*)\n";
    }
    
    template <class T> void g(T a){f(a);}
    
    int main()
    {
        g(99.9);
        g("hello");
        return 0;
    }
    
    void f(float)
    {
        cout << "f(float)\n";
    }
    On my machine, g(99.9); calls f(float). It seems that the compiler is looking through the whole translation unit for an appropriate f(). I thought dependent names were bound at the point of instantiation though, which in this case would be just before the start of main().

    What is the significance of the instantiation point if names found after the instantiation point are too available for binding?

  2. #2
    Registered User
    Join Date
    Jun 2005
    Posts
    6,815
    Quote Originally Posted by DL1 View Post
    I thought dependent names were bound at the point of instantiation though, which in this case would be just before the start of main().
    That's my understanding.
    Quote Originally Posted by DL1 View Post
    What is the significance of the instantiation point if names found after the instantiation point are too available for binding?
    The significance of the instantiation point is that your code should not call f(float), unless there is a declaration of f(float) in scope seen by the compiler before main().

    If your compiler is behaving as you describe, it is not correctly implementing the standard with respect to implementation points. However, it's not alone in that: quite a few otherwise good quality compilers get this thing wrong. This is often, as I understand it, because they do the work of instantiating templates after having scanned a complete source file. I recall one system a few years back in which template instantiation was managed by a smart linker (as opposed to compiler in the "compile - link - run" chain) - that system showed this sort of behaviour.
    Right 98% of the time, and don't care about the other 3%.

    If I seem grumpy or unhelpful in reply to you, or tell you you need to demonstrate more effort before you can expect help, it is likely you deserve it. Suck it up, Buttercup, and read this, this, and this before posting again.

  3. #3
    Registered User
    Join Date
    Jun 2008
    Location
    Somewhere in Europe
    Posts
    99
    Thanks. That's reassuring. I wonder though whether the declaration of f(float) wouldn't in fact have to be before the template definition to be considered, since floats don't have an associated namespace.

  4. #4
    Registered User
    Join Date
    Jun 2005
    Posts
    6,815
    Quote Originally Posted by DL1 View Post
    Thanks. That's reassuring. I wonder though whether the declaration of f(float) wouldn't in fact have to be before the template definition to be considered, since floats don't have an associated namespace.
    No it doesn't (and it's got nothing to do with namespaces).

    The rule of thumb (possibly not completely accurate, but usually close enough) the instantiation point is just before the point or scope where the template needs to be instantiated. At that point, in your example, both the template and the g() and the f() functions needed to instantiate it need to be visible to the compiler. There is no requirement that the f() be defined before g().
    Right 98% of the time, and don't care about the other 3%.

    If I seem grumpy or unhelpful in reply to you, or tell you you need to demonstrate more effort before you can expect help, it is likely you deserve it. Suck it up, Buttercup, and read this, this, and this before posting again.

  5. #5
    Registered User
    Join Date
    Jun 2008
    Location
    Somewhere in Europe
    Posts
    99
    The standard says this:

    "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 (...) and from the definition context."

    And Bjarne Stroustrup says:

    "Built-in types do not have an associated namespace. Consequently, dependent name resolution do not provide overload resolution between declarations seen before and after a template definition For example:

    Code:
    int f(int);
    
    	void ff(int);
    	void ff(char);
    
    	template T g(T t) { ff(t); return f(t); }
    
    	char f(char);
    
    	char c = g('a');   // calls ff(char); calls f(int) -- f(char) is not considered
    Obviously, such subtleties are best avoided."

    That suggests to me that, if f(X) is first declared after the template definition, it will only be considered if X is a user-defined type.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Code review
    By Elysia in forum C++ Programming
    Replies: 71
    Last Post: 05-13-2008, 09:42 PM
  2. Class warfare
    By disruptivetech in forum C++ Programming
    Replies: 13
    Last Post: 04-22-2008, 01:43 PM
  3. Header files and classes
    By disruptivetech in forum C++ Programming
    Replies: 5
    Last Post: 04-21-2008, 09:02 AM
  4. error: template with C linkage
    By michaels-r in forum C++ Programming
    Replies: 3
    Last Post: 05-17-2006, 08:11 AM
  5. include question
    By Wanted420 in forum C++ Programming
    Replies: 8
    Last Post: 10-17-2003, 03:49 AM