Up Next
Go up to News Articles
Go forward to MSVC++ 6.0 Compiles All But Two of the Second Edition's Example Programs

Comeau C++ Compiles All of the Second Edition's Example Programs

 By Dave Musser
Comeau Computing's C++ compiler successfully compiles all of the 100 or so example programs in STL Tutorial and Reference Guide, Second Edition. All but two compile in the compiler's strict mode. The Comeau compiler is actually a "front end" that can be combined with a C compiler and is available on many platforms. My tests were run on version on the Solaris platform and on version on Windows 2000. Another ingredient is the C++ Standard Library; for these tests I used libcomo as provided on the Comeau web site. Comeau adapted the STL part of this library from SGI STL.
  The one quirk encountered in these tests is that Comeau's strict implementation of the C++ Standard's template name lookup rules leads to undefined symbol errors when attempting to compile a couple of the example programs (ex05-22.cpp and ex19-02a.cpp). There was nothing that could be done, however, by changing the example programs; the problem lies in the algorithm header, where some function templates are used before they are defined. This order of definition is used in the SGI STL library without any problem because under older versions or interpretations of the template name lookup rules, as still implemented by SGI and many (perhaps all) other compilers, the function definitions are all visible at the point where the template instantiations occur. In a future version of libcomo, according to Greg Comeau, the function template definitions in the library will be reordered, where necessary, so that such undefined symbol errors do not occur.
  In the meantime, a temporary solution is available, as suggested by Greg Comeau: run the compiler in its non-strict mode, in which not all language rules are enforced. More selectively, one can specify the flag -no_dep_name on the compilation command line. This turns off some of the required template name lookup rules. The two problematic example programs compiled without error when that flag was used.
  In fact, on the Windows 2000 platform, the template name lookup issue does not even come up, because the Comeau front end is by default run in non-strict mode (in order to avoid other problems with the Microsoft compiler, which is used as the back-end C compiler.)
  All of the compiled programs execute correctly.
  For those who may be interested in the details of the template name lookup issue, read on:
  Consider the following little program:
#include <iostream>

template<typename T>
T foo(T x)
  return bar(x);

template<typename T>
T bar(T x)
  return x;

struct X {
  int a;

int main()
  X y;
  y.a = 5;
  std::cout << foo(y).a << std::endl;
  std::cout << foo(3) << std::endl;
  return 0;
When I compile this with Comeau's online compiler the output is:
Your Comeau C++ test results are as follows: 

Comeau C/C++ (Apr 12 2001 10:06:52) for ONLINE_EVALUATION
Copyright 1988-2001 Comeau Computing.  All rights reserved.
MODE:strict errors C++

"19595.c", line 6: error: identifier "bar" is undefined
    return bar(x);
          detected during instantiation of "T foo(T) [with T=int]" 

1 error detected in the compilation of "19595.c".

Tell others about http://www.comeaucomputing.com/tryitout !
In strict mode, with -tused, Compile failed
So why isn't bar(int) found as an instantiation of the bar function template, since it is known at the point of instantiation? Curiously, the compiler does find bar(X) when it does the foo(X) instantiation. Generally it seems to work for instantiations with class types but not for nonclass types, which made me suspect Koenig name lookup (also called dependent name lookup) was coming into play. However, I'd dismissed that idea because I was thinking that in this example foo, bar, and int are all in the global namespace, so there couldn't be any difference based on which namespaces are searched. But when I mentioned this to Doug Gregor (an RPI graduate student working on compiler optimization research), he pointed out that built-in types are not considered to be in the global namespace; they have no namespace associated with them at all (which is stated right there in the Koenig lookup rules in the C++ Standard, Section 3.4.2, clause 2). This was the main point I was missing. Greg Comeau confirmed this interpretation and elaborated on it in an email message:
The dependent name lookup rules require that:
* For _nondependent_ names:
   - they be looked up at the point of use in the template definition,
     And for _nondependent_ calls they perform overload resolution
* For _dependent_ calls
   - that the set of names considered is the set visible at the point
     of use in the template definition
   - any names made visible by argument-dependent lookup at the
     point of instantiation.

Since built-in types have no associated namespaces, then the lookup
_is_ different.  To wit, calls with only built-in types can _only_
resolve to names visible in the template definition.  (Furthermore,
names from dependent base classes are not visible to unqualified lookups.)
My thanks to both Doug Gregor and Greg Comeau for enlightenment on this thorny issue.


Up Next