[C++-sig] Re: long long unsigned issue...

Milind Patil milind_patil at hotmail.com
Sun May 4 00:30:32 CEST 2003


"David Abrahams" <dave at boost-consulting.com> wrote in message
news:uk7d8n8k7.fsf at boost-consulting.com...
> "Milind Patil" <milind_patil at hotmail.com> writes:
>
> > Hi,
...<snipped>...
> > Why wouldn't it try yo convert to long long unsigned int before trying
> > out int?
>
> Because of the order of your implicitly_convertible<...> invocations.
> Conversions to a C++ type (Y in this case) get tried in the order
> they're registered.  I know; it's confusing since that's the opposite
> of the way overloads work.
>

This clears some of my puzzlement. Thank you.

> Are you sure you want the implicitly_convertible invocations?  You
> don't need them in order to be able to compile and run the code above.
> The only reason you would need them was if you wanted to be able to
> pass a Python int or long directly to a wrapped C++ function accepting
> a Y or Y const& argument.
...<snipped>...
> That's because the constructor overloads get searched first (in
> reverse order), then converters to the argument types get searched (in
> forward order).
>
> In your original example it was finding Y(const Y&) and looking for a
> converter to the Y argument, finding the implicit converter for Python
> Int -> Y, which is a good enough match to use with long values.
>
> There's a lot of redundancy in all your declared constructors and
> especially in the use of implicitly_convertible.  You might consider
> starting with a minimal set of functionality (using unsigned long long
> only) and seeing if you can get that to do what you want.
>

You are right of course about this particular example not needing the
implicity_convertibles.

But, taking the toy example a step closer to the actual class I am
wrapping...

class Y {
  public:
    Y() : y(0L) { }
    Y(int y) : y(y) { }
    Y(long long unsigned int y) : y(y) { }
    Y(int s, const Y & y) : y(y << s/* toy usage*/) { }
    Y(Y const& rhs) : y(rhs.y) { }
    virtual ~Y() { }

    operator int() const { return y; }

    void operator=(Y const& y) {
        this->y = y.y;
    }

    long long unsigned int y;
};

BOOST_PYTHON_MODULE(hello)
{
    class_< Y >("Y", init<  >())
        .def(init< const Y & >())
        .def(init< int, const Y & >())
        .def(init< int >())
        .def(init< long long unsigned int >())
        .def_readwrite("y", &Y::y)
        .def("__int__", &Y::operator int)
    ;
}

This should work, ... intutively. But doesn't,  if I tried
to execute the python code...

z = hello.Y(2, 1)

Why should I now need
implicitly_convertible<int, Y>();
for it to work?

> > I am seeking a behaviour where python int is converted to c++ int
> > before constructing to c++ object Y, and python long is converted
> > to c++ long long unsigned int before constructing to c++ object Y.
>
> That might be difficult.  Guido and the lads are making it
> increasingly difficult to detect a difference between Python int and
> Python long, and plan to erase the distinction altogether soon.
>
> Do you really need to handle the cases differently?
>

Not explicitly. But consider if I want to do

z = hello.Y(~0)
or
z = hello.Y(-1)

This is best converted to Y(int) constructor. But python still insists
on calling the Y(long long unsigned int) constructor and craps out saying
about bad argument type.

> -- 
> Dave Abrahams
> Boost Consulting
> www.boost-consulting.com

Part of the c++ library I am wrapping is a bit vector library which
acts like a c++ builtin type for most part. It is only when converting
python types to the bit vector object that differences become
visibile according to whether source type is signed or not.

I read up a bit on python long and learned that it is not like the
c++ long. It seems the python long is a structure and is not
width bound. How does boost handle python boost to long
conversion?

Thank you for the quick response.

Milind









More information about the Cplusplus-sig mailing list