Topic: export: Is this code legal?


Author: Gabriel Dos Reis <dosreis@cmla.ens-cachan.fr>
Date: Thu, 7 Feb 2002 18:32:19 GMT
Raw View
kanze@gabi-soft.de (James Kanze) writes:

[...]

| > However, in the above specific case where you have to deal with
| > fundamental types, you want to use std::transform() with a
| > functional object which does the formatting.
|
| Which is a fairly unnatural way of going about it.  Formatting is the
| job of operator<<.  Anything else is wierd (in C++, of course).

But then, the natural way you treat a vector in C++ is to view its as a
sequence to which you apply transformations; that isn't wierd ;-)

--
Gabriel Dos Reis, dosreis@cmla.ens-cachan.fr

---
[ 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.research.att.com/~austern/csc/faq.html                ]





Author: kanze@gabi-soft.de (James Kanze)
Date: Thu, 7 Feb 2002 04:35:08 GMT
Raw View
Gabriel Dos Reis <dosreis@cmla.ens-cachan.fr> wrote in message
news:<fly9i7epc8.fsf@jambon.cmla.ens-cachan.fr>...
> kanze@gabi-soft.de (James Kanze) writes:

> | I just encountered a similar problem; the code would have worked
> | with the older, CFront model, but I think the compiler (g++ 3.0)
> | was correct in refusing it today:

> That is a feature of Koenig lookup.  You can encounter the same
> problem without templates.

No.  Because in this case, I don't particularly want or need Koenig
lookup.  I want simple lookup.  In the case of templates, however, I
don't get it at the point of instantiation (although I used to); all I
get is Koenig lookup.

> However, if you use Herb's rule of Interface Principle then you
> should not encounter surprises :-)

I disagree.  In this particular case, of course, I can't apply the
Interface Principal anyway, since I'm not the author of the class;
std::vector<char> is part of the standard library.  The problem is
that in real life, you often have to "extend" the interface of an
existing class, at least if you want to make effective use of the
standard library.  (Had I just written a classical for loop for the
output, instead of using std::copy, the problem wouldn't have
appeared.)  Most of the time, I'll probably go for some sort of
wrapper class, but there are times when it just isn't worth the
bother.

> [...]

> | Am I correct that this code should not work, because the template
> | instantiation of ostream_iterator doesn't find the operator<< ;

> Yes, you're correct.

> | it wasn't in scope at the point the template was defined (in the
> | includes), and it can't be found by argument dependant lookup at
> | the point of instantiation?  And if I am correct, what is the
> | politically correct solution?

> Use Herb's Interface Principle.

In this case, it's illegal:-).  What I want to do is to extend the
interface of std::vector<char>.  According to Herb's Interface
Principle, everything in the interface must be in the namespace in
which the class was defined.  No problem: all I have to do is reopen
the namespace in which the class is defined, and add my operator<<
there.  Which, of course, is illegal if the namespace happens to be
std.

> However, in the above specific case where you have to deal with
> fundamental types, you want to use std::transform() with a
> functional object which does the formatting.

Which is a fairly unnatural way of going about it.  Formatting is the
job of operator<<.  Anything else is wierd (in C++, of course).

--
James Kanze                                   mailto:kanze@gabi-soft.de
Beratung in objektorientierer Datenverarbeitung --
                             -- Conseils en informatique orient   e objet
Ziegelh   ttenweg 17a, 60598 Frankfurt, Germany, T   l.: +49 (0)69 19 86 27

---
[ 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.research.att.com/~austern/csc/faq.html                ]





Author: kanze@gabi-soft.de (James Kanze)
Date: Tue, 5 Feb 2002 18:12:33 GMT
Raw View
google@vandevoorde.com (Daveed Vandevoorde) wrote in message
news:<52f2f9cd.0202021156.1fddcce6@posting.google.com>...
> Christopher Eltschka <celtschk@web.de> wrote in message
> news:<a3enpr$l1r$1@news.tuwien.ac.at>...

> > After having read some of the discussion about export in this
> > newsgroup, I'm wondering if the following code is legal (besides
> > the fact that I might have gotten the export qualification itself
> > wrong):

> > // file 1:

> > void f(int);

> > export template<class T> void foo(T t)
> > {
> >   f(t);
> > }

> > // file 2:

> > template<class T> void foo(T t);

> // As I think you imply yourself, this declaration should also
> // be marked "export".  (This is not entirely clear from the
> // standard, but seems agreed upon by the J16 committee.)

> > int main()
> > {
> >   foo(5);
> > }

> > Note that f(int) is not visible at the point of instantiation, but
> > is at the point of definition.

> Indeed, and that is good enough.  An ordinary lookup is done of "f"
> at that point and it is memorized to be merged with the results of
> an ADL at the point of instantiation.

I'm just curious: would this change if the template were not exported?

> > Would the answer change if f(int) were a static function?

> Yes, it would not be found in that case.  See 14.6.4.2/1 in the
> standard.

I just encountered a similar problem; the code would have worked with
the older, CFront model, but I think the compiler (g++ 3.0) was
correct in refusing it today:

    //  The necessary includes...

    std::ostream&
    operator<<( ostream& dest, std::vector< char > const& obj )
    {
        //  ...
    }

    int
    main()
    {
        std::set< std::vector< char > > s ;
        //  ...
        std::copy( s.begin(), s.end(),
                   std::ostream_iterator< std::vector< char > >( cout , "\n" ) ) ;
        return 0 ;
    }

Am I correct that this code should not work, because the template
instantiation of ostream_iterator doesn't find the operator<< ; it
wasn't in scope at the point the template was defined (in the
includes), and it can't be found by argument dependant lookup at the
point of instantiation?  And if I am correct, what is the politically
correct solution?  (I made it work by putting the operator<< in
namespace std, but I don't think that this is actually legal.)

--
James Kanze                                   mailto:kanze@gabi-soft.de
Beratung in objektorientierer Datenverarbeitung --
                             -- Conseils en informatique orient   e objet
Ziegelh   ttenweg 17a, 60598 Frankfurt, Germany, T   l.: +49 (0)69 19 86 27

---
[ 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.research.att.com/~austern/csc/faq.html                ]





Author: Gabriel Dos Reis <dosreis@cmla.ens-cachan.fr>
Date: Tue, 5 Feb 2002 18:54:09 GMT
Raw View
kanze@gabi-soft.de (James Kanze) writes:

| google@vandevoorde.com (Daveed Vandevoorde) wrote in message
| news:<52f2f9cd.0202021156.1fddcce6@posting.google.com>...
| > Christopher Eltschka <celtschk@web.de> wrote in message
| > news:<a3enpr$l1r$1@news.tuwien.ac.at>...
|
| > > After having read some of the discussion about export in this
| > > newsgroup, I'm wondering if the following code is legal (besides
| > > the fact that I might have gotten the export qualification itself
| > > wrong):
|
| > > // file 1:
|
| > > void f(int);
|
| > > export template<class T> void foo(T t)
| > > {
| > >   f(t);
| > > }
|
| > > // file 2:
|
| > > template<class T> void foo(T t);
|
| > // As I think you imply yourself, this declaration should also
| > // be marked "export".  (This is not entirely clear from the
| > // standard, but seems agreed upon by the J16 committee.)
|
| > > int main()
| > > {
| > >   foo(5);
| > > }
|
| > > Note that f(int) is not visible at the point of instantiation, but
| > > is at the point of definition.
|
| > Indeed, and that is good enough.  An ordinary lookup is done of "f"
| > at that point and it is memorized to be merged with the results of
| > an ADL at the point of instantiation.
|
| I'm just curious: would this change if the template were not exported?

No.  The two-phase name lookup rules also apply to templates defined
in the inclusion model.

| > Yes, it would not be found in that case.  See 14.6.4.2/1 in the
| > standard.
|
| I just encountered a similar problem; the code would have worked with
| the older, CFront model, but I think the compiler (g++ 3.0) was
| correct in refusing it today:

That is a feature of Koenig lookup.  You can encounter the same
problem without templates.  However, if you use Herb's rule of
Interface Principle then you should not encounter surprises :-)

[...]

| Am I correct that this code should not work, because the template
| instantiation of ostream_iterator doesn't find the operator<< ;

Yes, you're correct.

| it
| wasn't in scope at the point the template was defined (in the
| includes), and it can't be found by argument dependant lookup at the
| point of instantiation?  And if I am correct, what is the politically
| correct solution?

Use Herb's Interface Principle.

However, in the above specific case where you have to deal with
fundamental types, you want to use std::transform() with a functional
object which does the formatting.

--
Gabriel Dos Reis, dosreis@cmla.ens-cachan.fr

---
[ 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.research.att.com/~austern/csc/faq.html                ]





Author: Christopher Eltschka <celtschk@web.de>
Date: Fri, 1 Feb 2002 21:25:13 GMT
Raw View
After having read some of the discussion about export in this
newsgroup, I'm wondering if the following code is legal (besides the
fact that I might have gotten the export qualification itself wrong):

// file 1:

void f(int);

export template<class T> void foo(T t)
{
  f(t);
}

// file 2:

template<class T> void foo(T t);

int main()
{
  foo(5);
}


Note that f(int) is not visible at the point of instantiation, but is
at the point of definition.

Would the answer change if f(int) were a static function?

---
[ 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.research.att.com/~austern/csc/faq.html                ]





Author: google@vandevoorde.com (Daveed Vandevoorde)
Date: Sat, 2 Feb 2002 21:03:49 GMT
Raw View
Christopher Eltschka <celtschk@web.de> wrote in message news:<a3enpr$l1r$1@news.tuwien.ac.at>...
> After having read some of the discussion about export in this
> newsgroup, I'm wondering if the following code is legal (besides the
> fact that I might have gotten the export qualification itself wrong):
>
> // file 1:
>
> void f(int);
>
> export template<class T> void foo(T t)
> {
>   f(t);
> }
>
> // file 2:
>
> template<class T> void foo(T t);

// As I think you imply yourself, this declaration should also
// be marked "export".  (This is not entirely clear from the
// standard, but seems agreed upon by the J16 committee.)

> int main()
> {
>   foo(5);
> }
>
>
> Note that f(int) is not visible at the point of instantiation, but is
> at the point of definition.

Indeed, and that is good enough.  An ordinary lookup is done of
"f" at that point and it is memorized to be merged with the
results of an ADL at the point of instantiation.

> Would the answer change if f(int) were a static function?

Yes, it would not be found in that case.
See 14.6.4.2/1 in the standard.

 Daveed

---
[ 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.research.att.com/~austern/csc/faq.html                ]