class derivation in boost.python v2. Was Re: [C++-sig] LifetimeofPython object for a pointer argument

David Abrahams david.abrahams at rcn.com
Tue Feb 19 14:44:39 CET 2002


----- Original Message -----
From: "Min Xu" <minxu at sci.ccny.cuny.edu>

> Thanks.
>
> Your fix is great. It now reports the uninitialized base class though
> with the name prefixed by a digit such as 8geometry. -:)

Are you volunteering to follow up on the attached message to get better
error reports from GCC?

----------

There are a few places where error reporting in Boost.Python depends on
being able to show users a reasonable representation of a C++ type name.
Currently, we use typeid(x).name() to get the name. Most compilers produce a
good result, however g++ does not. I just ran a small experiment to see if
the type encoding scheme used by G++ could easily be deciphered, and it
appears that it can. If we want to improve error reporting with G++, it
should be relatively easy.

The enclosed program indicates the following encoding information:

v void
c char
h unsigned char
a signed char
i int
j unsigned int
i signed int
s short
l long
x long long
f float
d double
e long double
P% %*
R% %&
K% % const
V% %volatile
A##_% %[##]                an array of ## %s, e.g. A4_c => char[4]
##...                      A name of length ##, e.g. 3foo => foo
N%1%2...%nE   %1::%2::...%n    A qualified name, e.g. N3foo3barE => foo::bar
F%1%2...%nE   %1 ()(%2,...%n)  A function, e.g. PFicE => int (*)(char)

S_    Back-reference to the first name spelled ##..., e.g. PF3fooS_E => foo
(*)(foo)

S##_    Back-reference to the ##+2'th name, e.g. PF3foo3barS0_E => foo
(*)(bar,bar)

        Note that back-references increase the count, so:
            PF3fooS_3barS1_E => foo (*)(foo, bar, bar)
  not S0_ --------------^^^

M%1%2 %2 (%1::*)  Member pointer, e.g.  M3fooi => int (foo::*)
                                        M3fooFvvE => void (foo::*)(void)

%1I%2%3...%nE  %1<%2,%3...%n> class template, e.g. 3fooIilE => foo<int,long>
L%##   ##     non-type template parameter of type L and value ##, e.g.
                    3fooILi42E => foo<42>, where 42 is an int

I got stumped at function non-type template parameters:

3fooIXadL_Z1fvEEE => foo<f>, with template<void (*)()> class foo / void f()

     ^^^^^^^^^^^
3fooIXadsr6foobarNS0_1fEvEE => foo<foobar::f>,
     ^^^^^^^^^^^^^^^^^^^^^
    with template<void (foobar::*)()> class foo, void foobar::f()

---------

Anyway, if someone would like to translate this information into code (and
complete the job for non-type template parameters, if possible), we could
easily have better error reporting for g++ users.


-Dave

-------------


// Copyright David Abrahams 2002. Permission to copy, use,
// modify, sell and distribute this software is granted provided this
// copyright notice appears in all copies. This software is provided
// "as is" without express or implied warranty, and with no claim as
// to its suitability for any purpose.
#include <typeinfo>
#include <cstdio>
#include <utility>

#define DUMP(type) std::printf("%s %s\n", typeid(type).name(), #type)

namespace foo
{
  namespace young
  {
    struct egg {};
  }
  struct bar {};
  enum baz {};
}

struct foobar {
    struct baz {};
    void f();
};

template <class T, class U, long, int> struct Template {};

struct x {};
struct xx {};
struct xxx {};
struct xxxx {};

void f();

template <void (*)()> struct TemplateTwo {};
template <void (foobar::*)()> struct TemplateThree {};

int main()
{
    DUMP(char);
    DUMP(char*);
    DUMP(char const*);
    DUMP(char const volatile*);
    DUMP(char[20]);
    DUMP(unsigned char);
    DUMP(signed char);
    DUMP(int);
    DUMP(unsigned int);
    DUMP(unsigned int*);
    DUMP(unsigned int const*);
    DUMP(unsigned int volatile*);
    DUMP(unsigned int const volatile*);
    DUMP(signed int);
    DUMP(short);
    DUMP(long);
    DUMP(long long);
    DUMP(float);
    DUMP(double);
    DUMP(long double);
    DUMP(foobar);
    DUMP(foobar::baz);
    DUMP(foo::bar);
    DUMP(foo::baz);
    DUMP(foo::young::egg);

    DUMP(x (*)(x));
    DUMP(x (*)(xx,xx));
    DUMP(x (*)(xx,xxx,xxx));
    DUMP(x (*)(xx,xxx,xxxx,xxxx));

    DUMP(void (*)());
    DUMP(int (*)());
    DUMP(int& (*)());
    DUMP(void (*)(int));
    DUMP(void (*)(int&));
    DUMP(void (*)(int const&));
    DUMP(void (*)(int const volatile&));
    DUMP(void (*)(int,foobar));
    DUMP(foo::baz (foobar::*)(int,foobar));

    // work around macro issues
    typedef Template<long,char*,42,99> template_foobar_3;
    DUMP(template_foobar_3);
    typedef std::pair<int,std::pair<long,char> > pair_int_pair_long_char;
    DUMP(pair_int_pair_long_char);
    typedef std::pair<foobar,std::pair<foobar,std::pair<foo::baz,foo::baz> >
> pair_foobar_pair_foobar_pair_foobaz_foobaz;
    DUMP(pair_foobar_pair_foobar_pair_foobaz_foobaz);

    typedef TemplateTwo<f> template_two_f;
    DUMP(template_two_f);
    typedef TemplateThree<&foobar::f> template_three_f;
    DUMP(template_three_f);
}







More information about the Cplusplus-sig mailing list