This is the mail archive of the libstdc++@gcc.gnu.org mailing list for the libstdc++ project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: type traits, reflection, and whatnot


Phil Edwards <phil@jaj.com> writes:

| On Sun, Jan 12, 2003 at 02:13:16PM +0100, Gabriel Dos Reis wrote:
| > compiler a la sizeof, e.g. __is_fundamental(T), __is_scalar(T), while
| > others are implemented at the library level, more or less like
| > <typeinfo> or <exception>.
| [...]
| > There would be little (or no) need for specializations if we choose
| > the "right" primitives.
| 
| Initially I liked the proposal's suggestion of a single operator,
| __traits_of, which evaluates to a bitmask containing the various traits.
| Then __is_foo<T>::value = __traits_of(T) & FOO_MASK for each 'foo' trait.
| (The suggestion of multiple operators, __is_class, __is_union, etc, was
| also in the proposal, but the thought of so many additional extention
| operators bothered me.)
| 
| The major difficulty with that approach, as I see it, is providing an
| out-of-line definition of is_foo::value.

Hmm, can you elaborate on he difficulty you're talking about?  E.g.,
what is difficult about

    // type_traits.h

    namespace std
    {
       template<tyename T>
         struct is_scalar {
             static const bool value = __is_scalar(T);
         };

       template<typename T>
          const bool is_scalar<T>::value;
    }

?

  Right now the language requires
| it, and even after core issue 48 relaxes the requirement, GCC currently
| is not optimizing away the need for storage (like 2.x did).
| 
| As it happens, that was the criterion which shaped my current approach,
| which (in the library) simply provides forward declarations for each of
| the classes, e.g.,
| 
|     template <typename _T> struct is_void;
| 
| When they are used,
| 
|     bool b = std::is_void<int>::value;
| 
| a rarely-taken code path in pt.c starts to instantiate the template,
| notices that the type is still incomplete, then checks for the presence
| of one of the traits classes. 

Ah, yes, I've thought about this strategy in the past, and finally
concluded that it is too fragile and less scalable.  As far as I'm
concerned about compile-time reflection, I think it ought to be
possible to reuse some (if not all) bits in C-land (think about the
current implementation of <tgmath.h>) without having to jump through
many hoops nor requiring C++ syntax.

| It then specializes the type "on the fly,"
| with the specialization looking like
| 
|     template <>
|       struct is_void<int> : public __gnu_cxx::__false_type
|       {
|       };
| 
| where the base classes are taken from the proposal and modified only
| enough to fit into v3's naming scheme.  This lets us implement as many
| traits as we wish without having to worry about defining 'value' members,
| and pay only for the space of 2 bool's.

I don't think this is an intrinsic advantage of the path you're
taking.  Let me rewrite what I proposed earlier as:

   template<typename T>
     struct is_scalar : __gnu_cxx::_Bool2Type<__is_scalar(T)> 
     {
     };

Again here, you just have the space for 2 bools.  What I meant is the
space saving is not intrisinc to hardwiring is_XXX<> directly into
pt.c.  On the other hand hardwiring things in pt.c means one has to
check many places for special templates.  Many checks means equally
opportunities to miss bits.

[...]

| > | The win is that none of the data structures used to handle the ss13s need
| > | to be initialized in the compiler unless we see the new pragma.
| > 
| > I do not believe we need pragmas.  I certainly do want it be possible
| > to use some of the type traits machinery without having to include
| > whathever header or saying whatever pragmas.
| 
| Well, the original idea was to extend the library more than anything else.
| Getting the machinery without including the header seems like bypassing much
| of the idea.  (Not necessarily a bad thing, if that's what we decide to do.)

Not at all.  The library part just provides *Standard C++ syntax* --
think of it as a way of extending the language with new keywords
without marking them keywords, but valling them library components.

| Which part(s) of the machinery did you have in mind?

Most of the query traits (i.e. is_XXX, has_XXX).
I'm not sure there are many specializations about the rest -- I don't
think there are so much.

| > Pragmas are useful when used appropriately, but I'm not sure there are
| > need or even convenient here.
| 
| I'm not wedded to pragmas, but it was by far the easiest way to signal,
| "from now on, recognize these name specially," once the appropriate header
| was included.

The sizeof framework is even easier.

-- Gaby


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]