Boost logo

Boost :

From: Aleksey Gurtovoy (alexy_at_[hidden])
Date: 2000-12-19 11:58:05


William Ward wrote:
> From: "David Abrahams" <abrahams_at_[hidden]>
> > Here's a shot-in-the-dark workaround. I have no idea if it's even really
> > legal C++:
> >
> > tempate< int X>
> > class Test
> > {
> > struct GenerateOps
> > : boost::less_than_comparable1<Test<X>
> > , boost::equality_comparable<Test<X>
> > , boost::addable<Test<X>
> > , boost::subtractable<Test<X>
> > , boost::multipliable<Test<X>
> > , boost::dividable<Test<X>
> > > > > > > > {};
> > static GenerateOps;
> > .....
> > };
> >

Funny, I was going to answer you with almost exactly the same solution as
Dave did :).

> I tried the workaround, it does prevent the size bloat
> but it cannot recognise the operators in Test, e.g even though += is
> defined, this workaround
> will give the error that there is no + operator defined if + is called
> in the application.

Static member wouldn't work here (at least without additional efforts),
because "The implicit instantiation of class template does not cause any
static data members of that class to be implicitly instantiated." However,
all my attempts to apply such "additional efforts" that, I thought, would
make the above technique work, have failed miserably :(. What scares me is
unanimity with which all compilers reject the code; it makes me think that
there are some details in the language which I don't know about, and which
make the code illegal... For example, the following code is rejected by all
the compilers I've tried it on (MSVC6.3, CW6.0, Comeau 4.2.44b), with the
same error (Comeau) - "no operator "+" matches these operands, operand types
are: test<int> + test<int>":

template<class T>
struct test {
  struct operators_gen
    : boost::addable< test<T> >
    {};

  test(operators_gen const& = operators_gen()) {} // should implicitly
  // instantiate operators_gen when the constructor call is compiled
  // (14.7.1 para 9); this instantiation, in its turn, should cause the
  // instantiation of the boost::addable< test<T> >'s friend function
  // test<T> operator+(test<T>, const test<T>&) (14.5.3 para 5)

  test& operator+=(test const&) { return *this; } // 1
};

void foo() {
  test<int>() + test<int>();
}

The strangest thing here is that if you comment out 'operator+=' (line 1),
MSVC won't even notice that (well, no surprise here), which means that on
this compiler the friend function is indeed never instantiated; BUT, Comeau
does complain and the error messages clearly indicate that the instantiation
we need have really took place:

"12026.c", line 3: error: no operator "+=" matches these operands
            operand types are: test<int> += const test<int>
    friend T operator+(T x, T const& y) { return x += y; }
                                                   ^
          detected during:
            instantiation of class "addable<T> [with T=test<int>]" at line 9
            instantiation of "test<T>::test(const test<T>::operators_gen &)
                      [with T=int]" at line 14

"12026.c", line 14: error: no operator "+" matches these operands
            operand types are: test<int> + test<int>
    test<int>() + test<int>();
                ^

"12026.c", line 3: warning: function "operator+" was declared but never
          referenced
    friend T operator+(T x, T const& y) { return x += y; }
             ^
What puzzles me is why then the generated instantiation of 'operator+'
specialization doesn't participate in overload resolution process. Could
someone clarify the issue??

--Aleksey


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