[LiDIA] LiDIA and GCC 3.3

LiDIA Administrator lidiaadm at cdc.informatik.tu-darmstadt.de
Wed Sep 10 12:25:41 CEST 2003


Hi,

I think I know why gcc 3.3 accepted your second version (the one with
a variable of type F initialized with 0)...

On Tue, Sep 09, 2003 at 04:29:15PM -0700, Justin C. Walker wrote:
> Continuing the sequel:
> 
> On Monday, September 8, 2003, at 06:55 AM, Stefan.Neis at t-online.de 
> wrote:
> 
> >LiDIA Administrator schrieb:
> >>For either call to succeed, the compiler needs to
> >>construct a
> >>LiDIA::alg_number from the integer constant 0. Because of
> >>the default
> [snip]
> >And typically, both are "wrong" (i.e. not giving the desired result
> >anyway). Either make that
> >"alg_number z = bigint(0);" (initialize z with the zero of the
> >"currently used" number field) or just
> >"alg_number z;" (default constructor initialized it with the zero
> >element of the "currently used" number field anyway).

Note this is true for your initial version, since gcc 3.3 tries
to make all arguments fit a call of 
operator!=(alg_num const&, alg_num const&). I.e., it tries a
constructor call alg_num(0), which is (a) ambiguous and (b) would not
yield the intended result anyway.

> I'm not sure this works well; the type in question is really 
> parameterized, i.e., the code reads
>   Matrix<F> mrels;
>   ...
>   if (mrels(j,i)!=0)
>   ...
> 
> so I think I have to have
>   F z=???;
> where ??? is pretty generic (i.e., '0').  Will 'F' always initialize z 
> to 0 (whatever '0' is for type 'F')?  Is
> 
>   F z = F(0);
> 
> a good bet?

Since I don't know the types for which you instantiate your template,
I cannot answer your question. For number types (bigints, alg_num,
...) I'd typically expect that the default constructor creates an
object representing the zero in the corresponding ring. But there are
no guarantees.

Anyway, the reason that gcc 3.3 accepts your second version is the
fact that when your template is instantiated, the line 

  F z = 0;

is expanded to 
 
  algnum z = 0;

And algnum is not a typedef, but a subclass of alg_number! You
probably have only one constructor in this class that can accept a
single 0.

[...]
> On Monday, September 8, 2003, at 06:28 AM, LiDIA Administrator wrote:
> 
> >The most straight forward way around your problem seems to change the
> >offending line into
> >
> >  if(mrels(j,i).is_zero()) { /* ... */ }
> 
> I tried this as well, and the compiler returned service with this:
> 
> modularcalc.cc: In member function `void
>    ModularCalculator<F>::display_basisfree() [with F = intmod]':
> modularcalc.cc:1576:   instantiated from here
> modularcalc.cc:627: error: `is_zero' undeclared (first use this 
> function)
> modularcalc.cc:627: error: (Each undeclared identifier is reported only 
> once
>    for each function it appears in.)
> modularcalc.cc: In member function `void
>    ModularCalculator<F>::display_basisfree() [with F = charmod]':
> modularcalc.cc:1579:   instantiated from here
> modularcalc.cc:627: error: `is_zero' undeclared (first use this 
> function)
> 
> and bailed.

Well, that's no surprise if the other types for which you instantiate
your template (intmod, charmod) don't have a member function is_zero()...

I propose you define a function template

  template<typename T>
  bool is_zero(T const& t) {
    return t == 0;
  }

and you provide specializations for the types where the primary
template won't compile or won't yield correct results (e.g. algnum):

  template<>
  bool is_zero<algnum>(algnum const& a) {
    return a.is_zero();
  }

Then you replace the line 

  if(mrels(i,j)!=0) {

by 

  if(!is_zero(mrels(i,j)) {

An alternative would be the use of type traits that contain, e.g., a
class variable zero which you can compare mrels(i,j) with. I don't
know which solution makes more sense in the long run in your specific
situation.


BTW, I tried the attached test programms with several gcc releases.
gcc 3.3 and 3.3.1 reject the ambiguous constructor call. gcc 3.1
through 3.2.3 spuriously accept it. There is no mention of the this
bug in gcc's bug database, though.

Regards

Christoph

-- 
http://www.informatik.tu-darmstadt.de/TI/Mitarbeiter/cludwig.html
LiDIA: http://www.informatik.tu-darmstadt.de/TI/LiDIA/Welcome.html

-------------- next part --------------
#include <LiDIA/alg_number.h>

using namespace LiDIA;

class not_implemented {
};

template<typename T> 
class Matrix {
public:
  T const& operator()(long row, long col) const {
    throw not_implemented();
  }
};

class algnum : public alg_number {
};

typedef Matrix<algnum> AlgnumMatrix;

void f(AlgnumMatrix const& mrels) {
  long i = 0;
  long j = 0;

  try {
    if(mrels(i,j)!=0) {
//    if(!mrels(i,j).is_zero()) {
      std::cout << "Surprise!\n";
    }
  }
  catch(not_implemented const& e) {
    std::cout << "Exception caught\n";
  }
}

int main(int argc, char** argv) {
  AlgnumMatrix m;
  f(m);

  return 0;
}


More information about the LiDIA mailing list