
Hello scipy, I'm working on the bool_ops.h file in sparse/sparsetools which wraps numpy bool type for the c++ routines. Currently it just does typedef npy_int8 npy_bool_wrapper; So the underlying int can roll over to zero, giving a False when we should have a True. I'm trying to make a class which inherits from npy_int8, then override the addition operators to behave like normal boolean arithmetic (1 + 1 = 1). But I'm having a few problems. When I try to do something simple like: class npy_bool_wrapper : public npy_int8 {}; I get an error for that line: error: expected class-name before '{' token When I try to implement it like a class template, like in complex_ops.h template <class c_type, class npy_type> class bool_wrapper : public npy_type {}; typedef bool_wrapper<int, npy_int8> npy_bool_wrapper; I get: error: base type 'signed char' fails to be a struct or class type

On 26 Jun 2013 17:18, "Blake Griffith" <blake.a.griffith@gmail.com> wrote:
Hello scipy, I'm working on the bool_ops.h file in sparse/sparsetools
which wraps numpy bool type for the c++ routines. Currently it just does
typedef npy_int8 npy_bool_wrapper;
So the underlying int can roll over to zero, giving a False when we
should have a True. I'm trying to make a class which inherits from npy_int8, then override the addition operators to behave like normal boolean arithmetic (1 + 1 = 1). But I'm having a few problems.
When I try to do something simple like:
class npy_bool_wrapper : public npy_int8 {};
I get an error for that line:
error: expected class-name before '{' token
In c++, user classes can't inherit from primitive types. Thus spake Bjarne. Make a memory-layout compatible class (i.e., one with a single npy_bool member), and then cast back and forth as needed? -n

26.06.2013 19:34, Nathaniel Smith kirjoitti: [clip]
In c++, user classes can't inherit from primitive types. Thus spake Bjarne.
Make a memory-layout compatible class (i.e., one with a single npy_bool member), and then cast back and forth as needed?
This may also needs appropriate constructors and operator=() npy_bool_wrapper() { value = 0; } npy_bool_wrapper(int x) { value = x ? 1 : 0; } npy_bool_wrapper& operator=(npy_bool_wrapper& x) { value = x; } and ditto possibly for += and other operators. -- Pauli Virtanen

26.06.2013 19:34, Nathaniel Smith kirjoitti: [clip]
In c++, user classes can't inherit from primitive types. Thus spake Bjarne.
Make a memory-layout compatible class (i.e., one with a single npy_bool member), and then cast back and forth as needed?
I somehow doubt that class Foo { char b; }; assert(sizeof(b) == sizeof(char)); is guaranteed by C++ standards. However, we can just start inserting compiler-specific packing pragmas for those cases where it isn't true. For safety, however, it's probably best to include the assert statement in one of the routines. The compiler should optimize it away, and it will break scipy test suite if the file is miscompiled. -- Pauli Virtanen

So basically I define a class that behaves like bool, but add compiler specific parameters to make instance of this class 1 byte? On Wed, Jun 26, 2013 at 12:17 PM, Pauli Virtanen <pav@iki.fi> wrote:
26.06.2013 19:34, Nathaniel Smith kirjoitti: [clip]
In c++, user classes can't inherit from primitive types. Thus spake Bjarne.
Make a memory-layout compatible class (i.e., one with a single npy_bool member), and then cast back and forth as needed?
I somehow doubt that
class Foo { char b; };
assert(sizeof(b) == sizeof(char));
is guaranteed by C++ standards. However, we can just start inserting compiler-specific packing pragmas for those cases where it isn't true.
For safety, however, it's probably best to include the assert statement in one of the routines. The compiler should optimize it away, and it will break scipy test suite if the file is miscompiled.
-- Pauli Virtanen
_______________________________________________ SciPy-Dev mailing list SciPy-Dev@scipy.org http://mail.scipy.org/mailman/listinfo/scipy-dev

27.06.2013 00:22, Blake Griffith kirjoitti:
So basically I define a class that behaves like bool, but add compiler specific parameters to make instance of this class 1 byte?
Pretty much so, for known compilers (gcc, msvc). I'd also put an assertion somewhere in the code. Either inside one of the functions, or try to construct a compile-time assertion via some trickery. C++11 has static_assert that would do the job, but that's a bit too new standard to rely on. However, there are some tricks to do it in any case (check stackoverflow for "sizeof compile time assert"). -- Pauli Virtanen

On 27 Jun 2013 22:56, "Pauli Virtanen" <pav@iki.fi> wrote:
27.06.2013 00:22, Blake Griffith kirjoitti:
So basically I define a class that behaves like bool, but add compiler specific parameters to make instance of this class 1 byte?
Pretty much so, for known compilers (gcc, msvc).
I'd also put an assertion somewhere in the code. Either inside one of the functions, or try to construct a compile-time assertion via some trickery. C++11 has static_assert that would do the job, but that's a bit too new standard to rely on. However, there are some tricks to do it in any case (check stackoverflow for "sizeof compile time assert").
Also it's unlikely that any trickery will be needed on any real world compiler. Standard c++ guarantees you can cast between npy_bool* and npy_bool_wrapper*; the only concern is that arrays might not have the same memory layout. And I don't think any compiler will add padding to a 1 byte struct. chars don't need word alignment! (But of course I could be wrong.) -n

On Thu, Jun 27, 2013 at 4:19 PM, Nathaniel Smith <njs@pobox.com> wrote:
On 27 Jun 2013 22:56, "Pauli Virtanen" <pav@iki.fi> wrote:
27.06.2013 00:22, Blake Griffith kirjoitti:
So basically I define a class that behaves like bool, but add compiler specific parameters to make instance of this class 1 byte?
Pretty much so, for known compilers (gcc, msvc).
I'd also put an assertion somewhere in the code. Either inside one of the functions, or try to construct a compile-time assertion via some trickery. C++11 has static_assert that would do the job, but that's a bit too new standard to rely on. However, there are some tricks to do it in any case (check stackoverflow for "sizeof compile time assert").
Also it's unlikely that any trickery will be needed on any real world compiler. Standard c++ guarantees you can cast between npy_bool* and npy_bool_wrapper*; the only concern is that arrays might not have the same memory layout. And I don't think any compiler will add padding to a 1 byte struct. chars don't need word alignment! (But of course I could be wrong.)
IIRC, in ancient times, the Borland compiler added an identifying number as the first entry in all classes. Needless to say, that played hob with classes like complex. That innovation didn't last long. Chuck

On 30 Jun 2013 15:14, "Charles R Harris" <charlesr.harris@gmail.com> wrote:
On Thu, Jun 27, 2013 at 4:19 PM, Nathaniel Smith <njs@pobox.com> wrote:
On 27 Jun 2013 22:56, "Pauli Virtanen" <pav@iki.fi> wrote:
27.06.2013 00:22, Blake Griffith kirjoitti:
So basically I define a class that behaves like bool, but add
compiler
specific parameters to make instance of this class 1 byte?
Pretty much so, for known compilers (gcc, msvc).
I'd also put an assertion somewhere in the code. Either inside one of the functions, or try to construct a compile-time assertion via some trickery. C++11 has static_assert that would do the job, but that's a bit too new standard to rely on. However, there are some tricks to do it in any case (check stackoverflow for "sizeof compile time assert").
Also it's unlikely that any trickery will be needed on any real world compiler. Standard c++ guarantees you can cast between npy_bool* and npy_bool_wrapper*; the only concern is that arrays might not have the same memory layout. And I don't think any compiler will add padding to a 1 byte struct. chars don't need word alignment! (But of course I could be wrong.)
IIRC, in ancient times, the Borland compiler added an identifying number as the first entry in all classes. Needless to say, that played hob with classes like complex. That innovation didn't last long.
Not only is that a terrible idea, it is (these days) actually a violation of the standard. But the standard does allow padding *after* the sole element in a single-element struct. -n
participants (4)
-
Blake Griffith
-
Charles R Harris
-
Nathaniel Smith
-
Pauli Virtanen