Topic: Should failure to instantiate a function template abort compilation during overload resolution?


Author: hinnant@metrowerks.com (Howard Hinnant)
Date: Wed, 10 Aug 2005 14:47:24 GMT
Raw View
In article <1123642375.849913.19940@f14g2000cwb.googlegroups.com>,
 "Wu Yongwei" <wuyongwei@gmail.com> wrote:

> My current opinion is that failure to instantiate a template function
> should automatically remove it from the candidates of overload
> resolution.

Compiler writers are understandably apprehensive of being required to
back out of an arbitrarily complex function which generates an error.
By "back out", I mean the compiler would have to put itself in the exact
same state as it had before it began the function instantiation.  I'm
not saying it is impossible to do so, just that this would be a new and
non-trivial requirement on the compiler.

As mentioned in the c.l.c++.m thread, concepts (if accepted) may create
this requirement and may resolve your issue.

-Howard

---
[ 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: gcc@integrable-solutions.net (Gabriel Dos Reis)
Date: Wed, 10 Aug 2005 14:46:05 GMT
Raw View
"Wu Yongwei" <wuyongwei@gmail.com> writes:

| Howard Hinnant wrote:
| > CodeWarrior is experimenting with an enable_if-like return type on
| > std::distance so that this overload will not participate in overload
| > resolution if InputIterator isn't an iterator.  Your example on our
| > implementation will compile and set d == 2 at runtime.
|
| Thanks for your informatiom.  Do you think this is the way to go?  I
| mean, does anyone in the C++ committee realize that it might be a

The C++ committee realizes that uncontrolled argument dependent name
lookup causes problems in some circumstances.  The proper fix seems
unclear however.  Many people have different opinions about what the
fix should be. For the latests, google for "a modest proposal" and
"Herb Sutter", and the latest concept papers.

| defect in the Standard that violates the rationale of the std namespace

The issue has nothing specific to do with namespace std.  I would have
considered it a problem was the namespace called foobar and the
function called freebies.

---
[ 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: clcppmod-poster@not.a.valid.address ("Gianluca Silvestri")
Date: Wed, 10 Aug 2005 16:20:10 GMT
Raw View
"Howard Hinnant" <hinnant@metrowerks.com> ha scritto nel messaggio
news:hinnant-7A2DC8.09274510082005@syrcnyrdrs-03-ge0.nyroc.rr.com...
| In article <1123642375.849913.19940@f14g2000cwb.googlegroups.com>,
| "Wu Yongwei" <wuyongwei@gmail.com> wrote:
|
| > My current opinion is that failure to instantiate a template function
| > should automatically remove it from the candidates of overload
| > resolution.
|
| Compiler writers are understandably apprehensive of being required to
| back out of an arbitrarily complex function which generates an error.
| By "back out", I mean the compiler would have to put itself in the exact
| same state as it had before it began the function instantiation.  I'm
| not saying it is impossible to do so, just that this would be a new and
| non-trivial requirement on the compiler.
|

What about keeping in the overload set those function templates that now
cause a compile error , mark them in some way and proceed with overload
resolution. If one of them win the match then the compiler issue an error,
otherwise the best one is chosen.


---
Gianluca Silvestri

---
[ 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: hinnant@metrowerks.com (Howard Hinnant)
Date: Thu, 11 Aug 2005 05:26:24 GMT
Raw View
> Paul Mensonides's post seems decisive.

> The question is what is the intention of the standard,

I agree with Paul's analysis.

-Howard

---
[ 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: spam@smapguard.com ("Gene Bushuyev")
Date: Thu, 11 Aug 2005 05:31:38 GMT
Raw View
"Howard Hinnant" <hinnant@metrowerks.com> wrote in message
news:hinnant-7A2DC8.09274510082005@syrcnyrdrs-03-ge0.nyroc.rr.com...
> In article <1123642375.849913.19940@f14g2000cwb.googlegroups.com>,
> "Wu Yongwei" <wuyongwei@gmail.com> wrote:
>
>> My current opinion is that failure to instantiate a template function
>> should automatically remove it from the candidates of overload
>> resolution.
>
> Compiler writers are understandably apprehensive of being required to
> back out of an arbitrarily complex function which generates an error.

Compilers traditionally have problems implementing standard. It's not an
argument. If that were impossible (or at least impracticle) to do then it
would be an argument. It may be a particular compiler implementation has a
design that makes recovery difficult, but this is conceptually nothing
new, - the recovery is the same as the recovery from an exception, no
back-tracking is necessary. So maybe it's time to start writing compilers in
C++ to make it easier.

But that aside, at this point we are trying to understand what the standard
actually requires. And it looks to me that the standard prescribes the
following set of actions:

// --- almost c++ code for compiler ---

Function overload_resolution(function_name, arguments)
{
    set<Function> overload_set;
    set<Function> failed_set;
    for(Function function = parse_tree.functions.begin();
          function != parse_tree.functions.end(); ++function)
    if(function->name == function_name
        && function->check_lookup_rules())
    {
        if(function->is_a_template()
        {
            try
            {
                if(! function->is_explicitly_specialized())
                    template_arguments =
                        function->deduce_template_arguments(arguments); //
14.8.2
                instance = function->instantiate(template_arguments) //
14.7.1
                overload_set.insert(instance); // 14.8.3/1
            }
            catch(...)
            {
                failed_set.insert(*function); // only for reporting purposes
                // do nothing with this candidate according to 14.8.3/1
            }
        }
        else
            overload_set.insert(*function);
    }

    set<Function> matched_set = overload_set.find_best_viable_function();

    if(matched_set.empty())
        throw no_match_error(failed_set); // just a hint for user - not
required

    if(matched_set.size() > 1)
        throw many_match_error(matched_set);

    // don't instantiate templates unless necessary 14.7.1/9
    if(matched_function.is_a_template_instance())
         compiler.instantiated_function_set.insert(matched_function);

    return matched_function;
}

I'm sure I missed details, but I hope I got the general picture right.

- gene

---
[ 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: "Wu Yongwei" <wuyongwei@gmail.com>
Date: Thu, 11 Aug 2005 00:32:49 CST
Raw View
Gabriel Dos Reis wrote:
> "Wu Yongwei" <wuyongwei@gmail.com> writes:
> | Thanks for your informatiom.  Do you think this is the way to go?  I
> | mean, does anyone in the C++ committee realize that it might be a
>
> The C++ committee realizes that uncontrolled argument dependent name
> lookup causes problems in some circumstances.  The proper fix seems
> unclear however.  Many people have different opinions about what the
> fix should be. For the latests, google for "a modest proposal" and
> "Herb Sutter", and the latest concept papers.

Thanks for this useful info.

> | defect in the Standard that violates the rationale of the std namespace
>
> The issue has nothing specific to do with namespace std.  I would have
> considered it a problem was the namespace called foobar and the
> function called freebies.

Yes, you are right.  But logically my statement was not wrong either.
:-)

Best regards,

Yongwei

---
[ 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: pavel@despammed.com ("Pavel Kuznetsov")
Date: Thu, 11 Aug 2005 14:33:37 GMT
Raw View
Richard,

> template <typename T>
> struct A
> {
>    friend class B;
> };
>
> template <typename T>
> typename T::TYPE foo (T);     // Does use SFNAE
>
> template <typename T>
> typename A<T>::TYPE foo (T);  // Does not use SFNAE
>
> void foo (int);
>
> void bar ()
> {
>    foo (0);
> }
>
> // ...
>
> typedef int B;

I fail to see why you're saying that SFINAE does not take place in
the second case, and in fact the standard contains a similar example:

   14.8.2/2 <...> Type deduction may fail for the following reasons:
   <...>
   - Attempting to use a type in the qualifier portion of a qualified
     name that names a type when that type does not contain the
     specified member, or if the specified member is not a type where
     a type is required. [Example:
       template <class T> int f(typename T::B*);
       struct A {};
       struct C { int B; };
       int i = f<A>(0);
       int j = f<C>(0);
     ]

   14.8.3/1 <...> If, for a given function template, argument deduction
   fails, no such function is added to the set of candidate functions
   for that template.

> If the compiler did allow you to instantiate class bodies, it would then
> have a lot of difficulty back tracking.  In this example, a completely
> unrelated typedef would now generate an error since there is already a
> 'class B' declared in the namespace.

This is exactly what Comeau Online and VC++8 beta 2 has to say for your
example:

====

"ComeauTest.c", line 23: error: invalid redeclaration of type name "B"
(declared at
           line 4)
   typedef int B;
               ^

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

===

.\test.cpp(36) : error C2371: 'B' : redefinition; different basic types
         .\test.cpp(17) : see declaration of 'B'

--
Pavel

---
[ 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: pmenso57@comcast.net ("Paul Mensonides")
Date: Thu, 11 Aug 2005 14:34:33 GMT
Raw View
"Gene Bushuyev" wrote:
> "Howard Hinnant" <hinnant@metrowerks.com> wrote in message

>> Compiler writers are understandably apprehensive of being required to
>> back out of an arbitrarily complex function which generates an error.
>
> Compilers traditionally have problems implementing standard. It's not
> an argument. If that were impossible (or at least impracticle) to do
> then it would be an argument. It may be a particular compiler
> implementation has a design that makes recovery difficult, but this
> is conceptually nothing new, - the recovery is the same as the recovery from
> an exception, no
> back-tracking is necessary.

Not backtracking, per se, but transactional semantics on the symbol table and
other associated compiler state.  This could be done if (e.g.) all access to the
symbol table was indirected in such a way that a proxy (actually any number of
them) could be put between the symbol table and any modifications to it.  I.e.

+--------------+
| symbol table |
+--------------+
       |
       |
   interface

This would be the initial setup; all access to the symbol table is through
"interface".  When a tentative change to the symbol table could happen, the
compiler would put a proxy in:

+--------------+     +-------+
| symbol table | --- | proxy |
+--------------+     +-------+
                         |
                         |
                     interface

The proxy is basically another symbol table capable of reading from its parent
symbol table, but storing all writes inside itself.  Upon failure, the proxy is
discarded.  Upon success, any writes are committed to the symbol table.  Or,
more precisely, they are committed to whatever is the parent symbol table _or_
proxy in the chain.  I.e. a tentative change could occur inside another
tentative change, yielding something like:

+--------------+     +-------+     +-------+
| symbol table | --- | proxy | --- | proxy |
+--------------+     +-------+     +-------+
                                       |
                                       |
                                   interface

The problem is that it is likely to be extremely non-trivial for a compiler to
alter its entire code base to work this way (or some similar way).  It isn't a
simple change by any means.  I do believe that it is a worthwhile change,
however.  In a case like overload resolution, particularly, would-be candidate
functions that aren't even selected can create POI's, which, in turn, can cause
ODR violations (which aren't currently caught by compilers in many cases) in
another POI that is also created by a would-be candidate function that isn't
selected.  There is a serious risk of this kind of problem (which might well
compile anyway despite ODR violations) whenever overloads or specializations are
declared away from the primary template or set of overloads and away from the
types that they match.  For template specializations, this basically means that
it is dangerous to define any specialization that doesn't come either with the
primary template or with the type that the specialization matches.  E.g.
third-party template ABC + third-party type XYZ + user-specialization of ABC on
XYZ is a recipe for ODR violations--it is an implicit coupling between that
specialization and the entire rest of the program.  For overloaded functions,
especially in light of ADL (which makes namespaces act as interfaces in addition
to organizational tools), there isn't a systematic way to avoid the problem in
most cases.  This situation is a mess, and it would be at least an improvement
if the compiler was required to *not* create any POI's (IOW, instantiations)
related to any template overload that isn't selected by overload
resolution--whether if type deduction fails or not or whether tentative
instantiations succeed or not.  Doing so virtually requires some kind of
transactional semantics or backtracking.  Once you have that, it becomes
comparatively easy to extend SFINAE such that any "error" excludes the function
from the candidate set.  In turn, that provides the ability to do nearly
arbitrary concept checking as a library component without a special concept
checking language feature.

Regards,
Paul Mensonides


---
[ 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: hinnant@metrowerks.com (Howard Hinnant)
Date: Thu, 11 Aug 2005 14:38:54 GMT
Raw View
In article <42F9CFA3.4000006@cs.york.ac.uk>,
 caj@cs.york.ac.uk (chris jefferson) wrote:

> Howard Hinnant wrote:
> > In article <1123485075.096196.242990@g44g2000cwa.googlegroups.com>,
> >  wuyongwei@gmail.com wrote:
> >
> > CodeWarrior is experimenting with an enable_if-like return type on
> > std::distance so that this overload will not participate in overload
> > resolution if InputIterator isn't an iterator.  Your example on our
> > implementation will compile and set d == 2 at runtime.
> >
>
> I had thought about using a similar technique on many other of the
> functions in std::, for example to stop functions matching if they are
> given incorrect iterator types, which should hopefully lead to better
> (or at least much smaller) error messages. However I was under the
> impression that all functions had to have exactly the same signiture as
> they do in the standard? Am I wrong?

<shrug> I'm not positive.  If my modification can cause conforming
programs to behave differently than they're supposed to, you're right.
Else I get away with it under the as-if rule.  As far as I know I'm
getting away with it under as-if.  I've simply taken a few
non-conforming programs that have undefined behavior and assigned them
behavior my customers may find more pleasing.

But now that I've publicly stated that, I'm sure someone will show me a
counter example.  Like I said, it is an experiment. :-)  And in the
final analysis my customers will let me know whether or not it is
successful.

Because this is an experiment, I haven't treated all of the
std::algorithms this way.  I picked on std::distance because of my
perception that it was especially vulnerable to the problem reported by
the OP.

-Howard

---
[ 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: francis@robinton.demon.co.uk (Francis Glassborow)
Date: Thu, 11 Aug 2005 14:45:59 GMT
Raw View
In article <A1wKe.1540$dk5.1104@newssvr21.news.prodigy.com>, Gene
Bushuyev <spam@smapguard.com> writes
>Compilers traditionally have problems implementing standard. It's not an
>argument. If that were impossible (or at least impracticle) to do then it
>would be an argument. It may be a particular compiler implementation has a
>design that makes recovery difficult, but this is conceptually nothing
>new, - the recovery is the same as the recovery from an exception, no
>back-tracking is necessary. So maybe it's time to start writing compilers in
>C++ to make it easier.
Rolling back all the look-up tables that compilers create is certainly
not a trivial task, nor is dumping a copy of the current state before
every step that might result in the need to roll-back.

--
Francis Glassborow      ACCU
Author of 'You Can Do It!' see http://www.spellen.org/youcandoit
For project ideas and contributions: http://www.spellen.org/youcandoit/projects

---
[ 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: spam@smapguard.com ("Gene Bushuyev")
Date: Thu, 11 Aug 2005 18:50:11 GMT
Raw View
"Francis Glassborow" <francis@robinton.demon.co.uk> wrote in message
news:CpIPUlB0Xv+CFwQ1@robinton.demon.co.uk...
> In article <A1wKe.1540$dk5.1104@newssvr21.news.prodigy.com>, Gene Bushuyev
> <spam@smapguard.com> writes
>>Compilers traditionally have problems implementing standard. It's not an
>>argument. If that were impossible (or at least impracticle) to do then it
>>would be an argument. It may be a particular compiler implementation has a
>>design that makes recovery difficult, but this is conceptually nothing
>>new, - the recovery is the same as the recovery from an exception, no
>>back-tracking is necessary. So maybe it's time to start writing compilers
>>in
>>C++ to make it easier.
> Rolling back all the look-up tables that compilers create is certainly not
> a trivial task, nor is dumping a copy of the current state before every
> step that might result in the need to roll-back.

Well, this looks non-trivial because we are discussing a compiler
organization differently than a regular c++ program. If "compiler" and all
"tables" were classes, then all it boils down to is having local variables
(tables) that are either merged with global or discarded if the exception
(substitution failure) occured. That's how we are programming all the time
in the presence of exceptions, don't we. We don't make the changes and then
roll them back if an exception is thrown. We do the work on the side and
then swap or merge the results.

- gene

---
[ 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: gcc@integrable-solutions.net (Gabriel Dos Reis)
Date: Thu, 11 Aug 2005 19:32:17 GMT
Raw View
francis@robinton.demon.co.uk (Francis Glassborow) writes:

| In article <A1wKe.1540$dk5.1104@newssvr21.news.prodigy.com>, Gene
| Bushuyev <spam@smapguard.com> writes
| >Compilers traditionally have problems implementing standard. It's not an
| >argument. If that were impossible (or at least impracticle) to do then it
| >would be an argument. It may be a particular compiler implementation has a
| >design that makes recovery difficult, but this is conceptually nothing
| >new, - the recovery is the same as the recovery from an exception, no
| >back-tracking is necessary. So maybe it's time to start writing compilers in
| >C++ to make it easier.
| Rolling back all the look-up tables that compilers create is certainly
| not a trivial task,

The compiler may not need to roll back the look-up table.  It may just
needs to mark it as "dirty".  That is easier than effectively
implement rool back.

---
[ 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: gcc@integrable-solutions.net (Gabriel Dos Reis)
Date: Thu, 11 Aug 2005 19:40:48 GMT
Raw View
pmenso57@comcast.net ("Paul Mensonides") writes:

| "Gene Bushuyev" wrote:
| > "Howard Hinnant" <hinnant@metrowerks.com> wrote in message
|
| >> Compiler writers are understandably apprehensive of being required to
| >> back out of an arbitrarily complex function which generates an error.
| >
| > Compilers traditionally have problems implementing standard. It's not
| > an argument. If that were impossible (or at least impracticle) to do
| > then it would be an argument. It may be a particular compiler
| > implementation has a design that makes recovery difficult, but this
| > is conceptually nothing new, - the recovery is the same as the recovery from
| > an exception, no
| > back-tracking is necessary.
|
| Not backtracking, per se, but transactional semantics on the symbol
| table and other associated compiler state.

There is a fundamental truth to that; however, I've come to believe
that the most "interesting" aspects of the roll-back semantics have
been over-emphasized -- though I do not pretend it is a trivial
matter.

The most interesting bits happen when binding symbols to entities
(i.e. declarations) in scopes.  The scopes directly affected are
classes -- from instantiations.  At any given time, a class (or rather
a scope) has a "dirthy bit" with three possible values:

   (1) clean -- the class is known to be well-formed (either regular
       class or a class from a well-formed chain of instantiation).

   (2) dirthy -- this is the result of an ill-formed chain of
       instantiations.  In a compiler with proper transactional
       semantics, this class would probably not have existed.

   (3) unknown -- this class is on the list of pending instantiations
       and the it is not known yet whether the chain is well-formed
       or not.  If this class needs an instantiation that is
       ill-formed, it will be set to "dirthy".

That dirthy bit scheme allows a compiler to implement roll-back,
without resorting to "purely functional compiler".

If a program requires lots of arbitrary speculative instantiations,
the compiler may fill up available memory with lots of dirthy scopes,
but that is OK :-)

---
[ 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: Gabriel Dos Reis <gcc@integrable-solutions.net>
Date: Thu, 11 Aug 2005 15:06:05 CST
Raw View
hinnant@metrowerks.com (Howard Hinnant) writes:

| In article <42F9CFA3.4000006@cs.york.ac.uk>,
|  caj@cs.york.ac.uk (chris jefferson) wrote:
|
| > Howard Hinnant wrote:
| > > In article <1123485075.096196.242990@g44g2000cwa.googlegroups.com>,
| > >  wuyongwei@gmail.com wrote:
| > >
| > > CodeWarrior is experimenting with an enable_if-like return type on
| > > std::distance so that this overload will not participate in overload
| > > resolution if InputIterator isn't an iterator.  Your example on our
| > > implementation will compile and set d == 2 at runtime.
| > >
| >
| > I had thought about using a similar technique on many other of the
| > functions in std::, for example to stop functions matching if they are
| > given incorrect iterator types, which should hopefully lead to better
| > (or at least much smaller) error messages. However I was under the
| > impression that all functions had to have exactly the same signiture as
| > they do in the standard? Am I wrong?
|
| <shrug> I'm not positive.  If my modification can cause conforming
| programs to behave differently than they're supposed to, you're right.
| Else I get away with it under the as-if rule.  As far as I know I'm
| getting away with it under as-if.

A fundamental issue is that since users can add overloads of
"distance" in std::, the issue is not solved only if you
instruct them to code in a highly stylistic way (using exactly the
same trick as you or similar), otherwise you would have just paper
over a corner: any direct expression of the ideas run into the problem
you're attempting to solve.

|  I've simply taken a few
| non-conforming programs that have undefined behavior and assigned them
| behavior my customers may find more pleasing.

I don't believe the specific case under discussion invokes undefined
behaviour .

---
[ 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: "Wu Yongwei" <wuyongwei@gmail.com>
Date: Thu, 11 Aug 2005 23:49:15 CST
Raw View
Gabriel Dos Reis wrote:
> |  I've simply taken a few
> | non-conforming programs that have undefined behavior and assigned them
> | behavior my customers may find more pleasing.
>
> I don't believe the specific case under discussion invokes undefined
> behaviour.

Please show what the `defined' behaviour of this program is, which I
think is exactly we are discussing:

#include <vector>

int distance(const std::vector<int>& v1, const std::vector<int>& v2)
{
    return v1.size() - v2.size();
}

int main()
{
    std::vector<int> v1(3), v2(1);
    int d = distance(v1, v2);
    return 0;
}

Best regards,

Yongwei

---
[ 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: "Wu Yongwei" <wuyongwei@gmail.com>
Date: Fri, 12 Aug 2005 09:50:03 CST
Raw View
Wu Yongwei wrote:
> My current opinion is that failure to instantiate a template function
> should automatically remove it from the candidates of overload
> resolution.

When discussing this issue in GCC Bugzilla, Wolfgang Bangerth mentions
something that alerts me of some real technical difficulties (and
possibly the reason why the C++ committe decided the current
behaviour?).  Maybe I can summarize it this way (my words):

Since most compilers do not verify code validity until instantiated (I
think), it is hard to differentiate an instantiation error from a
program error.  And thus my suggestion can result in an incorrect
template function never recognized as an error.

Comments please.

Best regards,

Yongwei

---
[ 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: wuyongwei@gmail.com
Date: 8 Aug 2005 07:30:01 GMT
Raw View
The discussion in comp.lang.c++.moderated:

http://groups-beta.google.com/group/comp.lang.c++.moderated/browse_thread/thread/3c449572456c8592

Paul Mensonides's post seems decisive.  However, this failure is ugly,
counter-intuitive, and user-unfriendly (not to mention that the error
messages I have seen are all very confusing since they say everything
unrelated to the user's code).  Anyone knows of anything improved in
this aspect?

Best regards,

Yongwei

---
[ 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: hinnant@metrowerks.com (Howard Hinnant)
Date: Wed, 10 Aug 2005 01:06:20 GMT
Raw View
In article <1123485075.096196.242990@g44g2000cwa.googlegroups.com>,
 wuyongwei@gmail.com wrote:

> The discussion in comp.lang.c++.moderated:
>
> http://groups-beta.google.com/group/comp.lang.c++.moderated/browse_thread/thre
> ad/3c449572456c8592
>
> Paul Mensonides's post seems decisive.  However, this failure is ugly,
> counter-intuitive, and user-unfriendly (not to mention that the error
> messages I have seen are all very confusing since they say everything
> unrelated to the user's code).  Anyone knows of anything improved in
> this aspect?

CodeWarrior is experimenting with an enable_if-like return type on
std::distance so that this overload will not participate in overload
resolution if InputIterator isn't an iterator.  Your example on our
implementation will compile and set d == 2 at runtime.

-Howard

---
[ 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: spam@spamguard.com ("Gene Bushuyev")
Date: Wed, 10 Aug 2005 05:45:26 GMT
Raw View
"Howard Hinnant" <hinnant@metrowerks.com> wrote in message
news:hinnant-6B7192.21000609082005@syrcnyrdrs-03-ge0.nyroc.rr.com...
> In article <1123485075.096196.242990@g44g2000cwa.googlegroups.com>,
> wuyongwei@gmail.com wrote:
>
>> The discussion in comp.lang.c++.moderated:
>>
>> http://groups-beta.google.com/group/comp.lang.c++.moderated/browse_thread/thre
>> ad/3c449572456c8592
>>
>> Paul Mensonides's post seems decisive.  However, this failure is ugly,
>> counter-intuitive, and user-unfriendly (not to mention that the error
>> messages I have seen are all very confusing since they say everything
>> unrelated to the user's code).  Anyone knows of anything improved in
>> this aspect?
>
> CodeWarrior is experimenting with an enable_if-like return type on
> std::distance so that this overload will not participate in overload
> resolution if InputIterator isn't an iterator.  Your example on our
> implementation will compile and set d == 2 at runtime.

But the question is not whether it's possible to circumvent this problem in
std::distance or any other function for that matter. The question is what is
the intention of the standard, because after long discussion it's still not
clear. Should the failure to implicitly instantiate the return type during
argument deduction during overload resolution be a program error or does
14.8.3/1 kick in and function should be simply excluded from the overload
set of candidates (SFINAE), no error reported. If the first is the intention
of the standard then the following test case will or will not compile
depending on whether the definition  for "struct traits" is provided, which
is counterintuitive. If the second is the intention of the standard, then
all the best compilers are miserably failing. And here again is the test:

template<class T>
struct traits
#if defined(PROVIDE_DEFINITION)
{
  typedef typename T::no_such_type no_such_type;
}
#endif
;

template<class T> typename traits<T>::no_such_type foo(T);

int foo(int);

int test()
{
    return foo(0);
}

- gene

---
[ 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: "Wu Yongwei" <wuyongwei@gmail.com>
Date: Wed, 10 Aug 2005 00:45:38 CST
Raw View
Howard Hinnant wrote:
> CodeWarrior is experimenting with an enable_if-like return type on
> std::distance so that this overload will not participate in overload
> resolution if InputIterator isn't an iterator.  Your example on our
> implementation will compile and set d == 2 at runtime.

Thanks for your informatiom.  Do you think this is the way to go?  I
mean, does anyone in the C++ committee realize that it might be a
defect in the Standard that violates the rationale of the std namespace
and can be very confusing to innocent users that happen to define their
own versions of distance(std::...)?

My current opinion is that failure to instantiate a template function
should automatically remove it from the candidates of overload
resolution.

Comments please.

Best regards,

Yongwei

---
[ 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                       ]