Boost logo

Boost :

From: Kresimir Fresl (fresl_at_[hidden])
Date: 2002-05-02 16:05:37


Hi Joerg,

>>These changes (as well as those from my previous post)

> Did I miss any of your previous changes?

No. It was a typo -- it should be `my previous posts' (plural),
referring to all patches for g++ 3.0, 3.0.1, etc.
that I posted earlier.

>>To compile with `como', I used settings for g++, ie. I simply
>>added in `config.h':
>>---------------------------------------------------------------------
>>107a108,112
>> > #ifdef USE_COMO
>> >
>> > #define USE_GCC
>> >
>> > #endif
>>---------------------------------------------------------------------

> This seems arguable: you try to compile ublas under COMO with GCC
> specific deviations. IMO it would be preferable to insert a separate
> USE_COMO block into config.h.

I agree. It was just a quick & dirty provisional trick, because separate
USE_COMO block in `config.h' is not enough -- `#ifdef USE_GCC' in
all files should be checked, and, if necessary, changed to
`#if (defined USE_GCC) && (defined USE_COMO)' or something
similar. Maybe one day, when I'll have time ... ;o)

>>[[`non_zeros_' must be `mutable' in `sparse_vector_of_sparse_vector'
>>because const function `non_zeros()' (lines 998-1003) modifies it.]]

> The intended functionality in sparse_vector_of_sparse_vector::non_zeros() is
> achieved, if we declare a local
>
> size_type non_zeros = 0;
>
> and add the sizes of the rows/columns to it. Then the member non_zeros_
> doesn't need to be mutable.

If I understand correctly, there's no need for `non_zeros_' member then?

>>`como' also complains that
>>
>> "/home/krcko/include/ublas/iterator.h", line 519: error:
>> identifier "base" is undefined
>>
>>patch for `iterator.h' is:
>>-----------------------------------------------------------------------
>>24c24
>>< #ifdef USE_GCC
>>---
>> > #if (defined USE_GCC) && (!defined USE_COMO)

As I incorrectly ;o) made USE_COMO equal to USE_GCC,
this guard removes redundant definition of `struct iterator<>'.

>>506a507,509
>> > #ifdef USE_COMO
>> > using std::reverse_iterator<I>::base;
>> > #endif
[...]

> This is a change I simply do not understand. Do you have any explanation,
> why it is necessary to use the 'using' directive under COMO? IOW could this
> be a COMO deficiency?

I must admit that I am not sure that I understand it myself.
(BTW, what does `IOW' mean?)

`como' has `strict' (ie. ANSI) and `non-strict' mode of compilation. Only
the `strict' mode needs the `using' directive (but guard in line 24 is
of course needed in `non-strict' mode, too).

Some time ago I asked them about a similar problem.
To make the long story long ;o) I'll quote some parts from my letters
and from their replies.

 From my first letter:

>Here is an example which I tried to compile with your compiler:
>---------------------------------------------------
>#include <iterator>
>
>using namespace std; // don't kill me
>
>template <typename InputIt>
>class countdown_iterator :
> public iterator<
> typename iterator_traits<InputIt>::iterator_category,
> typename iterator_traits<InputIt>::value_type,
> typename iterator_traits<InputIt>::difference_type,
> typename iterator_traits<InputIt>::pointer,
> typename iterator_traits<InputIt>::reference
> >
>{
>public:
[...]
> reference operator*() const { return *it; }
> pointer operator->() const { return &*it; }
[...]
>protected:
> InputIt it;
>};
>
>When in `strict mode', compiler complains:
>-------------------------------------------------------------------
>"261.c", line 27: error: identifier "reference" is undefined
> reference operator*() const { return *it; }
>"261.c", line 28: error: identifier "pointer" is undefined
> pointer operator->() const { return &*it; }
>--------------------------------------------------------------------
>And when I insert
>--------------------------------------------------------------------
>typedef typename iterator_traits<InputIt>::pointer pointer;
>typedef typename iterator_traits<InputIt>::reference reference;
>--------------------------------------------------------------------
>before quoted lines, compilation succeds.
>
>Why the typedefs from `iterator<>' are not inherited when
>in `strict mode'? As far as I understand it, one of the
>main purposes of classes like `iterator<>'
>(or eg. `unary_function<>') is to ease the definition
>of required types for new iterators (or functors etc.).

Their reply:

>We expect to hear a lot about this shortly as compilers implement the new
>lookup rules. In short, names based upon templates must be identified in
>some way. So although the typedef per se isn't required, acknowledging
>SomeTemplate<SomeT>::SomeMember is because that template can't possible
>know the name with certainty (clearly, as you say, this compiles in
>non-strict mode, but again, we're talking about knowing the name with
>certainty, not the compilers best guess). In your case that's probably
>formally essentially this, talking about it conceptually:
>
> using iterator<
> typename iterator_traits<InputIt>::iterator_category,
> typename iterator_traits<InputIt>::value_type,
> typename iterator_traits<InputIt>::difference_type,
> typename iterator_traits<InputIt>::pointer,
> typename iterator_traits<InputIt>::reference
> > :: pointer;
>
>and so on. But since you know your pass iterator_traits<InputIt>::pointer
>(and reference) to you base class, you can of course use that too.

 From my next letter:

>To quote from `Comeau C++ Template FAQ':
>------------------------------------------------------------------
>template <typename T> class xyz { };
>[...]
>In particular, if T is a template parameter as it is in xyz above,
>then what does it mean for it to use say T::x? In other words,
>if the compiler does not know what T is until you instantiate it,
>how could it know what x is, since it is based upon T?
>------------------------------------------------------------------
>But `iterator_traits<>' is not a template parameter of
>`countdown_iterator<>'. `InputIt' is template parameter
>of `iterator_traits<>', but it seems to me that
>`iterator_traits<InputIt>::pointer' is the same thing
>(here: typename), whatever `InputIt' is.

And their reply:

>Right, but our template faq is simplistic in discussing that as we really
>only discuss T, but similar to say deduction, it (typename) involves more
>forms that just an unadorned T.
>
>This whole situation (``template dependent name lookup'') is going to be
>surprising to a lot of folks. At least we believe so. Some more on it
>follows:
>
>When template-dependent name lookup in templates is enabled, calls in
>templates are classified as
>"dependent" or "non-dependent" based on whether the arguments involve
>dependent types. In non-dependent calls, the name of the function to be
>called is looked up only in the context of
>the template definition. In dependent calls, the name is also looked up in
>the context of the point of instantiation, via argument-dependent lookup.
>
>To programmers, the "in English" translation of this is that template
>definitions must be parsed at their points of definition in the source
>code, rather than only during actual instantiations. That means that
to use
>this language feature the source code must be fully
standard-conforming with
>regard to use of "typename" and similar keywords in templates.
>
>This is going to be surprising because most existing code was not written
>using these rules and will
>therefore not compile in this mode, so dependent name lookup is off by
>default (except in strict mode). It can be enabled with the --dep_name
>command-line option.
>
>The following illustrates some of the most common code problems
encountered
>when using dependent name lookup:
>
>template <class T> struct B {
> void f();
>};
>
>template <class T> struct A : public B<T> {
> X x; // error: X not declared yet
>
> void g() {
> f(); // error: member of dependent base class not
> // visible for reference with unqualified name
> this->f(); // this form works
> h(1); // error: h(int) not declared yet (note that
> // argument-dependent lookup does not apply)
> }
>};
>
>struct X {};
>void h(int);
>A<int> ai;

So, that's it: `B<>::f()' in above example is
`std::reverse_iterator<>::base()'.

To return to your letter:

> I'd also prefer to write instead
>
> std::reverse_iterator<I>::base () += n;
>
> for example (libraries should be deliberate in using 'using' directives
> AFAIK). Does this work for COMO?

Yes, it works. But one needs only one `using' directive per class,
and I am a lazy person ;o)

They suggest

     this->base() += n;

which, we needn't be surprised, also works.

BTW, some time ago `rwgk' posted the patch with `this->base()'
for EDG compiler. His message can be found at:

     http://aspn.activestate.com/ASPN/Mail/Message/1158300

>>And finally, there are some missing includes in `traits.h':
>>--------------------------------------------------------------------------
>>19a20
>> > #include <cmath>
>>20a22
>> > #include <iterator>
>>--------------------------------------------------------------------------
>>[[<cmath> is needed for `std::fabs()' and `std::sqrt()' and
>><iterator> for iterator tags.]]

> Adopted. I believe, that the inclusion of <iterator> is needed because you
> define USE_GCC and USE_COMO at the same time.

Mea culpa. It wasn't `como' who complains about undefined
iterator tags, but g++ 2.96. `como' & g++ 3.1 are quite happy
without <iterator>.

> It looks like ublas is written in near standard C++ ;-). Thanks for your
> effort to check ublas with Comeau's compiler and
>
> Best Regards
>
> Joerg

I didn't make thorough tests yet (in particular, I didn't try banded,
symmetric, triangular and hermitean matrices), but in due time...

Sincerely,

fres


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk