Thread: typedef and typename

  1. #16
    Cat without Hat CornedBee's Avatar
    Join Date
    Apr 2003
    Posts
    8,895
    That is not exactly true. VC++ really wouldn't care about typename at all weren't it for the standard saying that it has to.
    There is nothing that prevents a compiler from parsing the template and storing it as an ambiguous parse tree until instantiation. A compiler following this strategy (and VC++ does that, more or less, based on its behaviour) has no need of type disambiguation.

    On the other hand, such a compiler also loses the ability for early syntax checking of templates. Consider this code:
    Code:
    int p;
    
    template <typename T> void foo()
    {
      some_template<T>::xyz * p;
      p->bar();
    }
    An early-checking compiler decides that xyz is not a type (no typename keyword) and thus treats the first statement as
    Code:
    lookup::operator *(some_template<T>::xyz, ::p);
    Then the second line is treated as
    Code:
    ::p->bar();
    Since the global p has type int, this is faulty and the early-checking compiler immediately complains. It does not require the template to be instantiated to complain! This is important in developing templates. (That's half the point of concepts.)

    The late-checking compiler must wait until somebody actually instantiates the code to see whether the p here is a local variable or binds to the global. Only then can it issue compile errors.

    Worse! Look at this modified example:
    Code:
    struct stru { void bar() { do_something(); } stru* operator ->() { return this; } };
    struct ct { void bar() { do_something_else(); } };
    stru operator *(int, const stru&) { return stru(); }
    
    stru something;
    
    template <typename T> struct templ { typedef ct xyz; };
    template <> struct templ<float> { static int xyz; };
    int templ<float>::xyz;
    
    template <typename T> void foo()
    {
      templ<T>::xyz * something;
      something->bar();
    }
    
    int main()
    {
      foo<int>();
      foo<float>();
    }
    Here, both interpretations of xyz are valid. The foo<int>() will have a local something of type ct* and thus call do_something_else() (yes, it's undefined because it's through an uninitialized pointer, but given that ct::bar() doesn't access the this pointer, this is what will happen in typical systems). The foo<float>() will only have a global something of type stru, and thanks to the operator ->, it will call stru::bar() and thus do_something().

    Yes, contrived, but it shows that the ambiguity is real and potentially dangerous.
    All the buzzt!
    CornedBee

    "There is not now, nor has there ever been, nor will there ever be, any programming language in which it is the least bit difficult to write bad code."
    - Flon's Law

  2. #17
    Registered User VirtualAce's Avatar
    Join Date
    Aug 2001
    Posts
    9,607
    Wow. Had no idea my little question would spawn such an interesting slew of posts. Excellent thread. Thanks all for some very good information and logical debate.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Use of a class in place of main( )?
    By Sebastiani in forum C++ Programming
    Replies: 15
    Last Post: 12-10-2008, 01:06 PM
  2. Need Partners (D&D fan preferably)
    By C_ntua in forum Game Programming
    Replies: 44
    Last Post: 11-22-2008, 09:21 AM
  3. Polynomials and ADT's
    By Emeighty in forum C++ Programming
    Replies: 20
    Last Post: 08-19-2008, 08:32 AM
  4. typedef VS typename
    By tilex in forum C++ Programming
    Replies: 9
    Last Post: 07-25-2004, 03:26 PM
  5. oh me oh my hash maps up the wazoo
    By DarkDays in forum C++ Programming
    Replies: 5
    Last Post: 11-30-2001, 12:54 PM