Topic: Clarification regarding compiler's compliance with the C++ standard


Author: bsodz_remove_this_and_nospam@msn.com ("Jim Friedman")
Date: Mon, 29 Mar 2004 18:08:59 +0000 (UTC)
Raw View
Note: all compilers and compilations discussed in this message occurred
under Windows XP using windows-based command-line compilers. I don't think
this makes a difference but I mention it upfront.

While attempting to compile the RegressionTest code of Andrei Alexandrescu's
(brilliant) loki library (http://sourceforge.net/projects/loki-lib/), April
13, 2003 version), and using Metrowerks C++ compiler version 3.2.2 build 396
(the latest I believe), I encountered a compiler error regarding a template
instantiation. After narrowing it down, I found that the class AssocVector
in loki/reference/AssocVector.h had a friend operator==() function and
others; this was the cause of the problem. I then coded a small test program
to isolate the problem. Here it is:

// begin code
template<class T> class holder
{
public:
    friend bool operator==(const holder& lhs, const holder& rhs)
    {
        return lhs.data_ == rhs.data_;      // this line generates the
                                            // instantiation error
    }
    T data_;
};

class foo {};

int main()
{
    holder<foo> bar;        // if "foo" is changed to "int", for example
                            // there are no problems
    return 0;
}
// end of code

It appeared that the compiler was instantiating the friend operator==()
function even though it is never used. Since there are no relational
operators that accept a class foo, an error is generated. Note as the
comment above says, change "foo" to "int" and everything compiles fine.
After trying the code with various compilers I had available, I made a chart
like this:
COMPILER      COMPILES?
Borland Version 5.5.1    yes
Comeau Version 4.3.3    yes
Digital Mars Version 8.38n   no
Gnu gcc Version 3.3.1 (cygwin)  yes
Intel Version 8.0     yes
Metrowerks Version 3.2.2 build 396  no
Microsoft VS6 Version 12.00.8804  yes
Microsoft VS7.1 Version 13.10.3077  yes
Open Watcom Version 1.2    no

At first I thought this was a bug in Metrowerks because most of the other
compilers compiled the code successfully. But then I checked out the ISO C++
standard [BS ISO/IEC 14882:2003 (Second Edition)], and I found the following
entries:

------------------------
Section 14.5.3 Friends [temp.friend]
5. When a function is defined in a friend function declaration in a class
template, the function is defined at each instantiation of the class
template. The function is defined even if it is never used. ... [Note: if
the function definition is ill-formed for a given specialization of the
enclosing class template, the program is ill-formed even if the function is
never used. ]

Section 14.7 Template instantiation and specialization [temp.spec]
4. An instantiated template can be either implicitly instantiated (14.7.1)
for a given argument list or be explicitly instantiated (14.7.2). A
specialization is a class, function, or a class member that is either
instantiated or explicitly specialized (14.7.3).

Section 1.3.4 ill-formed program [defns.ill.formed]
input to a C++ implementation that is not a well-formed program (1.3.14).

Section 1.3.14 well-formed program [defns.well.formed]
a C++ program constructed according to the syntax rules, diagnosable
semantic rules, and the One Definition Rule (3.2).
------------------------

It seems to me, according to these definitions (14.7), a specialization as
mentioned in 14.5.3 is not necessarily an explicit specialization and can be
a normal instantiation as in the test code. Also, the code meets the first
and the third requirements of 1.3.14, but what exactly are "diagnosable
semantic rules"? I think that the missing relational operator would qualify
as a violation. So (finally :) ) my questions are these: Am I right in
thinking that Metrowerks, et al. are correct and the others are wrong
according to the standard? And if so, should it be this way? It seems useful
that such code should compile if the friend function is not referenced, just
as a member function of a template class that is not referenced is not
checked semantically.

Jim Friedman <bsodz_remove_this_and_nospam@msn.com.nospam>



---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: AlbertoBarbati@libero.it (Alberto Barbati)
Date: Tue, 30 Mar 2004 05:03:32 +0000 (UTC)
Raw View
Jim Friedman wrote:
>
> [snips] So (finally :) ) my questions are these: Am I right in
> thinking that Metrowerks, et al. are correct and the others are wrong
> according to the standard? And if so, should it be this way? It seems useful
> that such code should compile if the friend function is not referenced, just
> as a member function of a template class that is not referenced is not
> checked semantically.
>

According to the current C++ standard, 14.5.3/5 leaves no doubt to me:
Metrowerks, Open Watcom and Digital Mars are right and the others are
wrong. However, it seems that you are not one who noticed this problem
as there is defect report in WP status about this issue:

http://anubis.dkuug.dk/jtc1/sc22/wg21/docs/cwg_defects.html#329

There is also a closed issue loosely related to this problem, whose
rationale looks quite insightful to me:

http://anubis.dkuug.dk/jtc1/sc22/wg21/docs/cwg_closed.html#47

--
Alberto

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]